camera_roll_manager_impl_unittest.cc 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/components/phonehub/camera_roll_manager_impl.h"
  5. #include "ash/components/phonehub/camera_roll_download_manager.h"
  6. #include "ash/components/phonehub/camera_roll_item.h"
  7. #include "ash/components/phonehub/camera_roll_thumbnail_decoder_impl.h"
  8. #include "ash/components/phonehub/fake_camera_roll_download_manager.h"
  9. #include "ash/components/phonehub/fake_message_receiver.h"
  10. #include "ash/components/phonehub/fake_message_sender.h"
  11. #include "ash/components/phonehub/proto/phonehub_api.pb.h"
  12. #include "ash/components/phonehub/util/histogram_util.h"
  13. #include "ash/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h"
  14. #include "ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
  15. #include "ash/services/secure_channel/public/cpp/client/fake_connection_manager.h"
  16. #include "ash/services/secure_channel/public/mojom/secure_channel_types.mojom.h"
  17. #include "base/callback.h"
  18. #include "base/strings/utf_string_conversions.h"
  19. #include "base/test/metrics/histogram_tester.h"
  20. #include "base/test/task_environment.h"
  21. #include "base/time/time.h"
  22. #include "testing/gtest/include/gtest/gtest.h"
  23. #include "third_party/abseil-cpp/absl/types/optional.h"
  24. #include "ui/gfx/image/image.h"
  25. #include "ui/gfx/image/image_skia.h"
  26. namespace ash {
  27. namespace phonehub {
  28. namespace {
  29. using BatchDecodeResult = CameraRollThumbnailDecoder::BatchDecodeResult;
  30. using BatchDecodeCallback =
  31. base::OnceCallback<void(BatchDecodeResult,
  32. const std::vector<CameraRollItem>&)>;
  33. using FeatureState = multidevice_setup::mojom::FeatureState;
  34. using FileTransferStatus = secure_channel::mojom::FileTransferStatus;
  35. const char kDownloadResultMetricName[] =
  36. "PhoneHub.CameraRoll.DownloadItem.Result";
  37. class FakeObserver : public CameraRollManager::Observer {
  38. public:
  39. FakeObserver() = default;
  40. ~FakeObserver() override = default;
  41. // CameraRollManager::Observer
  42. void OnCameraRollViewUiStateUpdated() override {
  43. on_camera_roll_items_changed_call_count_++;
  44. }
  45. int on_camera_roll_items_changed_call_count() const {
  46. return on_camera_roll_items_changed_call_count_;
  47. }
  48. void OnCameraRollDownloadError(
  49. CameraRollManager::Observer::DownloadErrorType error_type,
  50. const proto::CameraRollItemMetadata& metadata) override {
  51. last_download_error_ = absl::make_optional(error_type);
  52. }
  53. CameraRollManager::Observer::DownloadErrorType last_download_error() const {
  54. return last_download_error_.value();
  55. }
  56. private:
  57. int on_camera_roll_items_changed_call_count_ = 0;
  58. absl::optional<CameraRollManager::Observer::DownloadErrorType>
  59. last_download_error_ = absl::nullopt;
  60. };
  61. void PopulateItemProto(proto::CameraRollItem* item_proto, std::string key) {
  62. proto::CameraRollItemMetadata* metadata = item_proto->mutable_metadata();
  63. metadata->set_key(key);
  64. metadata->set_mime_type("image/png");
  65. metadata->set_last_modified_millis(123456789L);
  66. metadata->set_file_size_bytes(123456789L);
  67. proto::CameraRollItemThumbnail* thumbnail = item_proto->mutable_thumbnail();
  68. thumbnail->set_format(proto::CameraRollItemThumbnail_Format_JPEG);
  69. thumbnail->set_data("encoded_thumbnail_data");
  70. }
  71. // Verifies that the metadata of a generated item matches the corresponding
  72. // proto input.
  73. void VerifyMetadataEqual(const proto::CameraRollItemMetadata& expected,
  74. const proto::CameraRollItemMetadata& actual) {
  75. EXPECT_EQ(expected.key(), actual.key());
  76. EXPECT_EQ(expected.mime_type(), actual.mime_type());
  77. EXPECT_EQ(expected.last_modified_millis(), actual.last_modified_millis());
  78. EXPECT_EQ(expected.file_size_bytes(), actual.file_size_bytes());
  79. }
  80. } // namespace
  81. class FakeThumbnailDecoder : public CameraRollThumbnailDecoder {
  82. public:
  83. FakeThumbnailDecoder() = default;
  84. ~FakeThumbnailDecoder() override = default;
  85. void BatchDecode(const proto::FetchCameraRollItemsResponse& response,
  86. const std::vector<CameraRollItem>& current_items,
  87. BatchDecodeCallback callback) override {
  88. if (!pending_callback_.is_null()) {
  89. CompletePendingCallback(BatchDecodeResult::kCancelled);
  90. }
  91. last_response_ = response;
  92. pending_callback_ = std::move(callback);
  93. }
  94. void CompletePendingCallback(BatchDecodeResult result) {
  95. std::vector<CameraRollItem> items;
  96. if (result == BatchDecodeResult::kCompleted) {
  97. for (const proto::CameraRollItem& item_proto : last_response_.items()) {
  98. SkBitmap test_bitmap;
  99. test_bitmap.allocN32Pixels(1, 1);
  100. gfx::ImageSkia image_skia =
  101. gfx::ImageSkia::CreateFrom1xBitmap(test_bitmap);
  102. image_skia.MakeThreadSafe();
  103. gfx::Image thumbnail(image_skia);
  104. items.emplace_back(item_proto.metadata(), thumbnail);
  105. }
  106. }
  107. std::move(pending_callback_).Run(result, items);
  108. }
  109. private:
  110. proto::FetchCameraRollItemsResponse last_response_;
  111. BatchDecodeCallback pending_callback_;
  112. };
  113. class CameraRollManagerImplTest : public testing::Test {
  114. protected:
  115. CameraRollManagerImplTest() = default;
  116. CameraRollManagerImplTest(const CameraRollManagerImplTest&) = delete;
  117. CameraRollManagerImplTest& operator=(const CameraRollManagerImplTest&) =
  118. delete;
  119. ~CameraRollManagerImplTest() override = default;
  120. void SetUp() override {
  121. fake_multidevice_setup_client_ =
  122. std::make_unique<multidevice_setup::FakeMultiDeviceSetupClient>();
  123. fake_connection_manager_ =
  124. std::make_unique<secure_channel::FakeConnectionManager>();
  125. std::unique_ptr<FakeCameraRollDownloadManager>
  126. fake_camera_roll_download_manager =
  127. std::make_unique<FakeCameraRollDownloadManager>();
  128. fake_camera_roll_download_manager_ =
  129. fake_camera_roll_download_manager.get();
  130. SetCameraRollFeatureState(FeatureState::kEnabledByUser);
  131. camera_roll_manager_ = std::make_unique<CameraRollManagerImpl>(
  132. &fake_message_receiver_, &fake_message_sender_,
  133. fake_multidevice_setup_client_.get(), fake_connection_manager_.get(),
  134. std::move(fake_camera_roll_download_manager));
  135. camera_roll_manager_->thumbnail_decoder_ =
  136. std::make_unique<FakeThumbnailDecoder>();
  137. camera_roll_manager_->AddObserver(&fake_observer_);
  138. }
  139. void TearDown() override {
  140. camera_roll_manager_->RemoveObserver(&fake_observer_);
  141. }
  142. int GetOnCameraRollViewUiStateUpdatedCallCount() const {
  143. return fake_observer_.on_camera_roll_items_changed_call_count();
  144. }
  145. CameraRollManager::Observer::DownloadErrorType GetLastDownloadError() const {
  146. return fake_observer_.last_download_error();
  147. }
  148. int GetCurrentItemsCount() const {
  149. return camera_roll_manager_->current_items().size();
  150. }
  151. size_t GetSentFetchCameraRollItemsRequestCount() const {
  152. return fake_message_sender_.GetFetchCameraRollItemsRequestCallCount();
  153. }
  154. const proto::FetchCameraRollItemsRequest& GetSentFetchCameraRollItemsRequest()
  155. const {
  156. return fake_message_sender_.GetRecentFetchCameraRollItemsRequest();
  157. }
  158. size_t GetSentFetchCameraRollItemDataRequestCount() const {
  159. return fake_message_sender_.GetFetchCameraRollItemDataRequestCallCount();
  160. }
  161. const proto::FetchCameraRollItemDataRequest&
  162. GetRecentFetchCameraRollItemDataRequest() const {
  163. return fake_message_sender_.GetRecentFetchCameraRollItemDataRequest();
  164. }
  165. size_t GetSentInitiateCameraRollItemTransferRequestCount() const {
  166. return fake_message_sender_
  167. .GetInitiateCameraRollItemTransferRequestCallCount();
  168. }
  169. const proto::InitiateCameraRollItemTransferRequest&
  170. GetRecentInitiateCameraRollItemTransferRequest() const {
  171. return fake_message_sender_
  172. .GetRecentInitiateCameraRollItemTransferRequest();
  173. }
  174. // Verifies current items match the list of items in the last received
  175. // |FetchCameraRollItemsResponse|, and their thumbnails have been properly
  176. // decoded.
  177. void VerifyCurrentItemsMatchResponse(
  178. const proto::FetchCameraRollItemsResponse& response) const {
  179. EXPECT_EQ(response.items_size(), GetCurrentItemsCount());
  180. for (int i = 0; i < GetCurrentItemsCount(); i++) {
  181. const CameraRollItem& current_item =
  182. camera_roll_manager_->current_items()[i];
  183. VerifyMetadataEqual(response.items(i).metadata(),
  184. current_item.metadata());
  185. EXPECT_FALSE(current_item.thumbnail().IsEmpty());
  186. }
  187. }
  188. void CompleteThumbnailDecoding(BatchDecodeResult result) {
  189. static_cast<FakeThumbnailDecoder*>(
  190. camera_roll_manager_->thumbnail_decoder_.get())
  191. ->CompletePendingCallback(result);
  192. }
  193. void SetCameraRollFeatureState(FeatureState feature_state) {
  194. fake_multidevice_setup_client_->SetFeatureState(
  195. multidevice_setup::mojom::Feature::kPhoneHubCameraRoll, feature_state);
  196. }
  197. void UngrantAndroidStoragePermission() {
  198. android_storage_permission_granted_ = false;
  199. }
  200. void SendPhoneStatusSnapshot() {
  201. proto::PhoneStatusSnapshot snapshot;
  202. proto::CameraRollAccessState* access_state =
  203. snapshot.mutable_properties()->mutable_camera_roll_access_state();
  204. access_state->set_storage_permission_granted(
  205. android_storage_permission_granted_);
  206. fake_message_receiver_.NotifyPhoneStatusSnapshotReceived(snapshot);
  207. }
  208. void SendPhoneStatusUpdate(bool has_camera_roll_updates) {
  209. proto::PhoneStatusUpdate update;
  210. update.set_has_camera_roll_updates(has_camera_roll_updates);
  211. proto::CameraRollAccessState* access_state =
  212. update.mutable_properties()->mutable_camera_roll_access_state();
  213. access_state->set_storage_permission_granted(
  214. android_storage_permission_granted_);
  215. fake_message_receiver_.NotifyPhoneStatusUpdateReceived(update);
  216. }
  217. void SendFetchCameraRollItemDataResponse(
  218. const proto::CameraRollItemMetadata& item_metadata,
  219. proto::FetchCameraRollItemDataResponse::FileAvailability
  220. file_availability,
  221. int64_t payload_id) {
  222. proto::FetchCameraRollItemDataResponse response;
  223. *response.mutable_metadata() = item_metadata;
  224. response.set_file_availability(file_availability);
  225. response.set_payload_id(payload_id);
  226. fake_message_receiver_.NotifyFetchCameraRollItemDataResponseReceived(
  227. response);
  228. }
  229. void SendFileTransferUpdate(int64_t payload_id,
  230. FileTransferStatus status,
  231. uint64_t total_bytes,
  232. uint64_t bytes_transferred) {
  233. fake_connection_manager_->SendFileTransferUpdate(
  234. secure_channel::mojom::FileTransferUpdate::New(
  235. payload_id, status, total_bytes, bytes_transferred));
  236. }
  237. void VerifyFileTransferProgress(int64_t payload_id,
  238. FileTransferStatus status,
  239. uint64_t total_bytes,
  240. uint64_t bytes_transferred) {
  241. const secure_channel::mojom::FileTransferUpdatePtr& latest_update =
  242. fake_camera_roll_download_manager_->GetFileTransferUpdates(payload_id)
  243. .back();
  244. EXPECT_EQ(payload_id, latest_update->payload_id);
  245. EXPECT_EQ(status, latest_update->status);
  246. EXPECT_EQ(total_bytes, latest_update->total_bytes);
  247. EXPECT_EQ(bytes_transferred, latest_update->bytes_transferred);
  248. }
  249. void SetCurrentItems(std::vector<std::string> item_keys) {
  250. proto::FetchCameraRollItemsResponse response;
  251. for (const auto& item_key : item_keys) {
  252. PopulateItemProto(response.add_items(), item_key);
  253. }
  254. fake_message_receiver_.NotifyFetchCameraRollItemsResponseReceived(response);
  255. CompleteThumbnailDecoding(BatchDecodeResult::kCompleted);
  256. }
  257. CameraRollManager* camera_roll_manager() {
  258. return camera_roll_manager_.get();
  259. }
  260. secure_channel::FakeConnectionManager* fake_connection_manager() {
  261. return fake_connection_manager_.get();
  262. }
  263. FakeCameraRollDownloadManager* fake_camera_roll_download_manager() {
  264. return fake_camera_roll_download_manager_;
  265. }
  266. FakeMessageReceiver fake_message_receiver_;
  267. std::unique_ptr<multidevice_setup::FakeMultiDeviceSetupClient>
  268. fake_multidevice_setup_client_;
  269. base::test::TaskEnvironment task_environment_{
  270. base::test::TaskEnvironment::TimeSource::MOCK_TIME};
  271. base::HistogramTester histogram_tester_;
  272. private:
  273. FakeMessageSender fake_message_sender_;
  274. std::unique_ptr<secure_channel::FakeConnectionManager>
  275. fake_connection_manager_;
  276. FakeCameraRollDownloadManager* fake_camera_roll_download_manager_;
  277. std::unique_ptr<CameraRollManagerImpl> camera_roll_manager_;
  278. FakeObserver fake_observer_;
  279. bool android_storage_permission_granted_ = true;
  280. };
  281. TEST_F(CameraRollManagerImplTest, OnCameraRollItemsReceived) {
  282. SendPhoneStatusSnapshot();
  283. task_environment_.FastForwardBy(base::Seconds(10));
  284. proto::FetchCameraRollItemsResponse response;
  285. PopulateItemProto(response.add_items(), "key3");
  286. PopulateItemProto(response.add_items(), "key2");
  287. PopulateItemProto(response.add_items(), "key1");
  288. fake_message_receiver_.NotifyFetchCameraRollItemsResponseReceived(response);
  289. CompleteThumbnailDecoding(BatchDecodeResult::kCompleted);
  290. EXPECT_EQ(2, GetOnCameraRollViewUiStateUpdatedCallCount());
  291. VerifyCurrentItemsMatchResponse(response);
  292. histogram_tester_.ExpectUniqueTimeSample(
  293. "PhoneHub.CameraRoll.Latency.RefreshItems", base::Seconds(10),
  294. /*expected_bucket_count=*/1);
  295. }
  296. TEST_F(CameraRollManagerImplTest,
  297. OnCameraRollItemsReceivedWithCancelledThumbnailDecodingRequest) {
  298. SendPhoneStatusSnapshot();
  299. task_environment_.FastForwardBy(base::Seconds(10));
  300. proto::FetchCameraRollItemsResponse response;
  301. PopulateItemProto(response.add_items(), "key3");
  302. PopulateItemProto(response.add_items(), "key2");
  303. PopulateItemProto(response.add_items(), "key1");
  304. fake_message_receiver_.NotifyFetchCameraRollItemsResponseReceived(response);
  305. CompleteThumbnailDecoding(BatchDecodeResult::kCancelled);
  306. EXPECT_EQ(1, GetOnCameraRollViewUiStateUpdatedCallCount());
  307. EXPECT_EQ(0, GetCurrentItemsCount());
  308. EXPECT_TRUE(histogram_tester_
  309. .GetAllSamples("PhoneHub.CameraRoll.Latency.RefreshItems")
  310. .empty());
  311. }
  312. TEST_F(CameraRollManagerImplTest,
  313. OnCameraRollItemsReceivedWithPendingThumbnailDecodedRequest) {
  314. SendPhoneStatusSnapshot();
  315. task_environment_.FastForwardBy(base::Seconds(10));
  316. proto::FetchCameraRollItemsResponse first_response;
  317. PopulateItemProto(first_response.add_items(), "key2");
  318. PopulateItemProto(first_response.add_items(), "key1");
  319. fake_message_receiver_.NotifyFetchCameraRollItemsResponseReceived(
  320. first_response);
  321. task_environment_.FastForwardBy(base::Seconds(5));
  322. proto::FetchCameraRollItemsResponse second_response;
  323. PopulateItemProto(second_response.add_items(), "key4");
  324. PopulateItemProto(second_response.add_items(), "key3");
  325. fake_message_receiver_.NotifyFetchCameraRollItemsResponseReceived(
  326. second_response);
  327. CompleteThumbnailDecoding(BatchDecodeResult::kCompleted);
  328. // The first thumbnail decode request should be cancelled and the current item
  329. // set should be updated only once after the second request completes.
  330. EXPECT_EQ(2, GetOnCameraRollViewUiStateUpdatedCallCount());
  331. VerifyCurrentItemsMatchResponse(second_response);
  332. histogram_tester_.ExpectUniqueTimeSample(
  333. "PhoneHub.CameraRoll.Latency.RefreshItems", base::Seconds(15),
  334. /*expected_bucket_count=*/1);
  335. }
  336. TEST_F(CameraRollManagerImplTest, OnCameraRollItemsReceivedWithExistingItems) {
  337. SendPhoneStatusSnapshot();
  338. task_environment_.FastForwardBy(base::Seconds(10));
  339. proto::FetchCameraRollItemsResponse first_response;
  340. PopulateItemProto(first_response.add_items(), "key3");
  341. PopulateItemProto(first_response.add_items(), "key2");
  342. PopulateItemProto(first_response.add_items(), "key1");
  343. fake_message_receiver_.NotifyFetchCameraRollItemsResponseReceived(
  344. first_response);
  345. CompleteThumbnailDecoding(BatchDecodeResult::kCompleted);
  346. VerifyCurrentItemsMatchResponse(first_response);
  347. SendPhoneStatusUpdate(/*has_camera_roll_updates=*/true);
  348. task_environment_.FastForwardBy(base::Seconds(5));
  349. proto::FetchCameraRollItemsResponse second_response;
  350. PopulateItemProto(second_response.add_items(), "key4");
  351. // Thumbnails won't be sent with the proto if an item's data is already
  352. // available and up-to-date.
  353. PopulateItemProto(second_response.add_items(), "key3");
  354. second_response.mutable_items(1)->clear_thumbnail();
  355. PopulateItemProto(second_response.add_items(), "key2");
  356. second_response.mutable_items(2)->clear_thumbnail();
  357. fake_message_receiver_.NotifyFetchCameraRollItemsResponseReceived(
  358. second_response);
  359. CompleteThumbnailDecoding(BatchDecodeResult::kCompleted);
  360. EXPECT_EQ(3, GetOnCameraRollViewUiStateUpdatedCallCount());
  361. VerifyCurrentItemsMatchResponse(second_response);
  362. histogram_tester_.ExpectTimeBucketCount(
  363. "PhoneHub.CameraRoll.Latency.RefreshItems", base::Seconds(10),
  364. /*count=*/1);
  365. histogram_tester_.ExpectTimeBucketCount(
  366. "PhoneHub.CameraRoll.Latency.RefreshItems", base::Seconds(5),
  367. /*count=*/1);
  368. }
  369. TEST_F(CameraRollManagerImplTest,
  370. OnPhoneStatusUpdateReceivedWithoutCameraRollUpdates) {
  371. SendPhoneStatusUpdate(/*has_camera_roll_updates=*/false);
  372. EXPECT_EQ(0UL, GetSentFetchCameraRollItemsRequestCount());
  373. EXPECT_EQ(CameraRollManager::CameraRollUiState::SHOULD_HIDE,
  374. camera_roll_manager()->ui_state());
  375. EXPECT_EQ(1, GetOnCameraRollViewUiStateUpdatedCallCount());
  376. }
  377. TEST_F(CameraRollManagerImplTest,
  378. OnPhoneStatusUpdateReceivedWithCameraRollUpdates) {
  379. SendPhoneStatusUpdate(/*has_camera_roll_updates=*/true);
  380. EXPECT_EQ(1UL, GetSentFetchCameraRollItemsRequestCount());
  381. EXPECT_EQ(0,
  382. GetSentFetchCameraRollItemsRequest().current_item_metadata_size());
  383. EXPECT_EQ(CameraRollManager::CameraRollUiState::SHOULD_HIDE,
  384. camera_roll_manager()->ui_state());
  385. EXPECT_EQ(1, GetOnCameraRollViewUiStateUpdatedCallCount());
  386. }
  387. TEST_F(CameraRollManagerImplTest,
  388. OnPhoneStatusUpdateReceivedWithExistingItems) {
  389. SetCurrentItems({"key1", "key2", "key3"});
  390. SendPhoneStatusUpdate(/*has_camera_roll_updates=*/true);
  391. EXPECT_EQ(1UL, GetSentFetchCameraRollItemsRequestCount());
  392. EXPECT_EQ(CameraRollManager::CameraRollUiState::ITEMS_VISIBLE,
  393. camera_roll_manager()->ui_state());
  394. EXPECT_EQ(2, GetOnCameraRollViewUiStateUpdatedCallCount());
  395. EXPECT_EQ(3,
  396. GetSentFetchCameraRollItemsRequest().current_item_metadata_size());
  397. VerifyMetadataEqual(
  398. camera_roll_manager()->current_items()[0].metadata(),
  399. GetSentFetchCameraRollItemsRequest().current_item_metadata(0));
  400. VerifyMetadataEqual(
  401. camera_roll_manager()->current_items()[1].metadata(),
  402. GetSentFetchCameraRollItemsRequest().current_item_metadata(1));
  403. VerifyMetadataEqual(
  404. camera_roll_manager()->current_items()[2].metadata(),
  405. GetSentFetchCameraRollItemsRequest().current_item_metadata(2));
  406. }
  407. TEST_F(CameraRollManagerImplTest,
  408. OnPhoneStatusUpdateReceivedWithCameraRollSettingsDisabled) {
  409. SetCameraRollFeatureState(FeatureState::kDisabledByUser);
  410. SetCurrentItems({"key1", "key2"});
  411. SendPhoneStatusUpdate(/*has_camera_roll_updates=*/true);
  412. EXPECT_EQ(0UL, GetSentFetchCameraRollItemsRequestCount());
  413. EXPECT_EQ(CameraRollManager::CameraRollUiState::SHOULD_HIDE,
  414. camera_roll_manager()->ui_state());
  415. EXPECT_EQ(4, GetOnCameraRollViewUiStateUpdatedCallCount());
  416. EXPECT_EQ(0, GetCurrentItemsCount());
  417. }
  418. TEST_F(CameraRollManagerImplTest,
  419. OnPhoneStatusUpdateReceivedWithoutStoragePermission) {
  420. SetCurrentItems({"key1", "key2"});
  421. UngrantAndroidStoragePermission();
  422. SendPhoneStatusUpdate(/*has_camera_roll_updates=*/false);
  423. EXPECT_EQ(0UL, GetSentFetchCameraRollItemsRequestCount());
  424. EXPECT_EQ(CameraRollManager::CameraRollUiState::NO_STORAGE_PERMISSION,
  425. camera_roll_manager()->ui_state());
  426. EXPECT_EQ(2, GetOnCameraRollViewUiStateUpdatedCallCount());
  427. EXPECT_EQ(0, GetCurrentItemsCount());
  428. }
  429. TEST_F(CameraRollManagerImplTest, OnPhoneStatusSnapshotReceived) {
  430. SendPhoneStatusSnapshot();
  431. EXPECT_EQ(1UL, GetSentFetchCameraRollItemsRequestCount());
  432. EXPECT_EQ(CameraRollManager::CameraRollUiState::SHOULD_HIDE,
  433. camera_roll_manager()->ui_state());
  434. EXPECT_EQ(1, GetOnCameraRollViewUiStateUpdatedCallCount());
  435. }
  436. TEST_F(CameraRollManagerImplTest,
  437. OnPhoneStatusSnapshotReceivedWithCameraRollSettingDisabled) {
  438. SetCameraRollFeatureState(FeatureState::kDisabledByUser);
  439. SetCurrentItems({"key1", "key2"});
  440. SendPhoneStatusSnapshot();
  441. EXPECT_EQ(0UL, GetSentFetchCameraRollItemsRequestCount());
  442. EXPECT_EQ(CameraRollManager::CameraRollUiState::SHOULD_HIDE,
  443. camera_roll_manager()->ui_state());
  444. EXPECT_EQ(4, GetOnCameraRollViewUiStateUpdatedCallCount());
  445. EXPECT_EQ(0, GetCurrentItemsCount());
  446. }
  447. TEST_F(CameraRollManagerImplTest,
  448. OnPhoneStatusSnapshotReceivedWithoutStoragePermission) {
  449. SetCurrentItems({"key1", "key2"});
  450. UngrantAndroidStoragePermission();
  451. SendPhoneStatusSnapshot();
  452. EXPECT_EQ(0UL, GetSentFetchCameraRollItemsRequestCount());
  453. EXPECT_EQ(CameraRollManager::CameraRollUiState::NO_STORAGE_PERMISSION,
  454. camera_roll_manager()->ui_state());
  455. EXPECT_EQ(2, GetOnCameraRollViewUiStateUpdatedCallCount());
  456. EXPECT_EQ(0, GetCurrentItemsCount());
  457. }
  458. TEST_F(CameraRollManagerImplTest, OnFeatureStatesChangedToDisabled) {
  459. SendPhoneStatusSnapshot();
  460. SetCurrentItems({"key1", "key2"});
  461. SetCameraRollFeatureState(FeatureState::kDisabledByUser);
  462. EXPECT_EQ(CameraRollManager::CameraRollUiState::SHOULD_HIDE,
  463. camera_roll_manager()->ui_state());
  464. EXPECT_EQ(3, GetOnCameraRollViewUiStateUpdatedCallCount());
  465. EXPECT_EQ(0, GetCurrentItemsCount());
  466. }
  467. TEST_F(CameraRollManagerImplTest, FeatureProhibitedByPolicy) {
  468. SetCameraRollFeatureState(FeatureState::kProhibitedByPolicy);
  469. proto::PhoneStatusSnapshot snapshot;
  470. proto::CameraRollAccessState* access_state =
  471. snapshot.mutable_properties()->mutable_camera_roll_access_state();
  472. access_state->set_storage_permission_granted(true);
  473. fake_message_receiver_.NotifyPhoneStatusSnapshotReceived(snapshot);
  474. EXPECT_EQ(CameraRollManager::CameraRollUiState::SHOULD_HIDE,
  475. camera_roll_manager()->ui_state());
  476. }
  477. TEST_F(CameraRollManagerImplTest, DownloadItem) {
  478. SetCurrentItems({"key1"});
  479. const CameraRollItem& item_to_download =
  480. camera_roll_manager()->current_items().back();
  481. // Request to download the item that was added.
  482. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  483. EXPECT_EQ(1UL, GetSentFetchCameraRollItemDataRequestCount());
  484. EXPECT_EQ("key1", GetRecentFetchCameraRollItemDataRequest().metadata().key());
  485. // CameraRollManager should initiate transfer of the item after receiving
  486. // FetchCameraRollItemDataResponse.
  487. SendFetchCameraRollItemDataResponse(
  488. item_to_download.metadata(),
  489. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  490. /*payload_id=*/1234);
  491. EXPECT_EQ(1UL, GetSentInitiateCameraRollItemTransferRequestCount());
  492. EXPECT_EQ("key1",
  493. GetRecentInitiateCameraRollItemTransferRequest().metadata().key());
  494. EXPECT_EQ(1234,
  495. GetRecentInitiateCameraRollItemTransferRequest().payload_id());
  496. // Now the CameraRollManager should be ready to receive updates of the item
  497. // transfer.
  498. SendFileTransferUpdate(/*payload_id=*/1234, FileTransferStatus::kInProgress,
  499. /*total_bytes=*/1000, /*bytes_transferred=*/200);
  500. VerifyFileTransferProgress(/*payload_id=*/1234,
  501. FileTransferStatus::kInProgress,
  502. /*total_bytes=*/1000,
  503. /*bytes_transferred=*/200);
  504. SendFileTransferUpdate(/*payload_id=*/1234, FileTransferStatus::kSuccess,
  505. /*total_bytes=*/1000, /*bytes_transferred=*/1000);
  506. VerifyFileTransferProgress(/*payload_id=*/1234, FileTransferStatus::kSuccess,
  507. /*total_bytes=*/1000,
  508. /*bytes_transferred=*/1000);
  509. histogram_tester_.ExpectBucketCount(kDownloadResultMetricName,
  510. util::CameraRollDownloadResult::kSuccess,
  511. /*expected_count=*/1);
  512. }
  513. TEST_F(CameraRollManagerImplTest, DownloadItemAndCurrentItemsChanged) {
  514. SetCurrentItems({"key1"});
  515. const CameraRollItem& item_to_download =
  516. camera_roll_manager()->current_items().back();
  517. // Request to download the item that was added.
  518. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  519. SendFetchCameraRollItemDataResponse(
  520. item_to_download.metadata(),
  521. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  522. /*payload_id=*/1234);
  523. SendFileTransferUpdate(/*payload_id=*/1234, FileTransferStatus::kInProgress,
  524. /*total_bytes=*/1000, /*bytes_transferred=*/200);
  525. // The item being downloaded is no longer in the current item set, but the
  526. // download should still finish normally.
  527. SendPhoneStatusUpdate(/*has_camera_roll_updates=*/true);
  528. SetCurrentItems({"key2"});
  529. SendFileTransferUpdate(/*payload_id=*/1234, FileTransferStatus::kSuccess,
  530. /*total_bytes=*/1000, /*bytes_transferred=*/1000);
  531. VerifyFileTransferProgress(/*payload_id=*/1234, FileTransferStatus::kSuccess,
  532. /*total_bytes=*/1000,
  533. /*bytes_transferred=*/1000);
  534. }
  535. TEST_F(CameraRollManagerImplTest,
  536. DownloadItemWhenFileNoLongerAvailableOnPhone) {
  537. SetCurrentItems({"key1"});
  538. const CameraRollItem& item_to_download =
  539. camera_roll_manager()->current_items().back();
  540. // Request to download the item that was added.
  541. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  542. SendFetchCameraRollItemDataResponse(
  543. item_to_download.metadata(),
  544. proto::FetchCameraRollItemDataResponse::NOT_FOUND,
  545. /*payload_id=*/1234);
  546. EXPECT_EQ(0UL, GetSentInitiateCameraRollItemTransferRequestCount());
  547. histogram_tester_.ExpectBucketCount(
  548. kDownloadResultMetricName,
  549. util::CameraRollDownloadResult::kFileNotAvailable,
  550. /*expected_count=*/1);
  551. }
  552. TEST_F(CameraRollManagerImplTest, DownloadItemFailedWithInvalidFileName) {
  553. SetCurrentItems({"key1"});
  554. const CameraRollItem& item_to_download =
  555. camera_roll_manager()->current_items().back();
  556. // Request to download the item that was added.
  557. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  558. fake_camera_roll_download_manager()->set_expected_create_payload_files_result(
  559. CameraRollDownloadManager::CreatePayloadFilesResult::kInvalidFileName);
  560. SendFetchCameraRollItemDataResponse(
  561. item_to_download.metadata(),
  562. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  563. /*payload_id=*/1234);
  564. EXPECT_EQ(0UL, GetSentInitiateCameraRollItemTransferRequestCount());
  565. EXPECT_EQ(CameraRollManager::Observer::DownloadErrorType::kGenericError,
  566. GetLastDownloadError());
  567. histogram_tester_.ExpectBucketCount(
  568. kDownloadResultMetricName,
  569. util::CameraRollDownloadResult::kInvalidFileName,
  570. /*expected_count=*/1);
  571. }
  572. TEST_F(CameraRollManagerImplTest, DownloadItemFailedWithInsufficientStorage) {
  573. SetCurrentItems({"key1"});
  574. const CameraRollItem& item_to_download =
  575. camera_roll_manager()->current_items().back();
  576. // Request to download the item that was added.
  577. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  578. fake_camera_roll_download_manager()->set_expected_create_payload_files_result(
  579. CameraRollDownloadManager::CreatePayloadFilesResult::
  580. kInsufficientDiskSpace);
  581. SendFetchCameraRollItemDataResponse(
  582. item_to_download.metadata(),
  583. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  584. /*payload_id=*/1234);
  585. EXPECT_EQ(0UL, GetSentInitiateCameraRollItemTransferRequestCount());
  586. EXPECT_EQ(
  587. CameraRollManager::Observer::DownloadErrorType::kInsufficientStorage,
  588. GetLastDownloadError());
  589. histogram_tester_.ExpectBucketCount(
  590. kDownloadResultMetricName,
  591. util::CameraRollDownloadResult::kInsufficientDiskSpace,
  592. /*expected_count=*/1);
  593. }
  594. TEST_F(CameraRollManagerImplTest, DownloadItemFailedWithDuplicatedPayloadId) {
  595. SetCurrentItems({"key1"});
  596. const CameraRollItem& item_to_download =
  597. camera_roll_manager()->current_items().back();
  598. // Request to download the item that was added.
  599. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  600. fake_camera_roll_download_manager()->set_expected_create_payload_files_result(
  601. CameraRollDownloadManager::CreatePayloadFilesResult::
  602. kPayloadAlreadyExists);
  603. SendFetchCameraRollItemDataResponse(
  604. item_to_download.metadata(),
  605. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  606. /*payload_id=*/1234);
  607. EXPECT_EQ(0UL, GetSentInitiateCameraRollItemTransferRequestCount());
  608. EXPECT_EQ(CameraRollManager::Observer::DownloadErrorType::kGenericError,
  609. GetLastDownloadError());
  610. histogram_tester_.ExpectBucketCount(
  611. kDownloadResultMetricName,
  612. util::CameraRollDownloadResult::kPayloadAlreadyExists,
  613. /*expected_count=*/1);
  614. }
  615. TEST_F(CameraRollManagerImplTest, DownloadItemFailedWitDuplicatedFilePath) {
  616. SetCurrentItems({"key1"});
  617. const CameraRollItem& item_to_download =
  618. camera_roll_manager()->current_items().back();
  619. // Request to download the item that was added.
  620. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  621. fake_camera_roll_download_manager()->set_expected_create_payload_files_result(
  622. CameraRollDownloadManager::CreatePayloadFilesResult::kNotUniqueFilePath);
  623. SendFetchCameraRollItemDataResponse(
  624. item_to_download.metadata(),
  625. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  626. /*payload_id=*/1234);
  627. EXPECT_EQ(0UL, GetSentInitiateCameraRollItemTransferRequestCount());
  628. EXPECT_EQ(CameraRollManager::Observer::DownloadErrorType::kGenericError,
  629. GetLastDownloadError());
  630. histogram_tester_.ExpectBucketCount(
  631. kDownloadResultMetricName,
  632. util::CameraRollDownloadResult::kNotUniqueFilePath,
  633. /*expected_count=*/1);
  634. }
  635. TEST_F(CameraRollManagerImplTest, DownloadItemTransferFailed) {
  636. SetCurrentItems({"key1"});
  637. const CameraRollItem& item_to_download =
  638. camera_roll_manager()->current_items().back();
  639. // Request to download the item that was added.
  640. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  641. SendFetchCameraRollItemDataResponse(
  642. item_to_download.metadata(),
  643. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  644. /*payload_id=*/1234);
  645. SendFileTransferUpdate(/*payload_id=*/1234, FileTransferStatus::kInProgress,
  646. /*total_bytes=*/1000, /*bytes_transferred=*/200);
  647. SendFileTransferUpdate(/*payload_id=*/1234, FileTransferStatus::kFailure,
  648. /*total_bytes=*/0, /*bytes_transferred=*/0);
  649. EXPECT_EQ(CameraRollManager::Observer::DownloadErrorType::kNetworkConnection,
  650. GetLastDownloadError());
  651. histogram_tester_.ExpectBucketCount(
  652. kDownloadResultMetricName,
  653. util::CameraRollDownloadResult::kTransferFailed,
  654. /*expected_count=*/1);
  655. }
  656. TEST_F(CameraRollManagerImplTest, DownloadItemTransferCanceled) {
  657. SetCurrentItems({"key1"});
  658. const CameraRollItem& item_to_download =
  659. camera_roll_manager()->current_items().back();
  660. // Request to download the item that was added.
  661. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  662. SendFetchCameraRollItemDataResponse(
  663. item_to_download.metadata(),
  664. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  665. /*payload_id=*/1234);
  666. SendFileTransferUpdate(/*payload_id=*/1234, FileTransferStatus::kInProgress,
  667. /*total_bytes=*/1000, /*bytes_transferred=*/200);
  668. SendFileTransferUpdate(/*payload_id=*/1234, FileTransferStatus::kCanceled,
  669. /*total_bytes=*/0, /*bytes_transferred=*/0);
  670. EXPECT_EQ(CameraRollManager::Observer::DownloadErrorType::kNetworkConnection,
  671. GetLastDownloadError());
  672. histogram_tester_.ExpectBucketCount(
  673. kDownloadResultMetricName,
  674. util::CameraRollDownloadResult::kTransferCanceled,
  675. /*expected_count=*/1);
  676. }
  677. TEST_F(CameraRollManagerImplTest, DownloadItemAndRegisterPayloadFileFail) {
  678. SetCurrentItems({"key1"});
  679. const CameraRollItem& item_to_download =
  680. camera_roll_manager()->current_items().back();
  681. // Request to download the item that was added.
  682. camera_roll_manager()->DownloadItem(item_to_download.metadata());
  683. fake_connection_manager()->set_register_payload_file_result(false);
  684. SendFetchCameraRollItemDataResponse(
  685. item_to_download.metadata(),
  686. proto::FetchCameraRollItemDataResponse::AVAILABLE,
  687. /*payload_id=*/1234);
  688. EXPECT_EQ(0UL, GetSentInitiateCameraRollItemTransferRequestCount());
  689. histogram_tester_.ExpectBucketCount(
  690. kDownloadResultMetricName,
  691. util::CameraRollDownloadResult::kTargetFileNotAccessible,
  692. /*expected_count=*/1);
  693. }
  694. TEST_F(CameraRollManagerImplTest, ItemsClearedWhenDeviceDisconnected) {
  695. fake_connection_manager()->SetStatus(
  696. secure_channel::ConnectionManager::Status::kConnected);
  697. proto::FetchCameraRollItemsResponse response;
  698. PopulateItemProto(response.add_items(), "key3");
  699. PopulateItemProto(response.add_items(), "key2");
  700. PopulateItemProto(response.add_items(), "key1");
  701. fake_message_receiver_.NotifyFetchCameraRollItemsResponseReceived(response);
  702. CompleteThumbnailDecoding(BatchDecodeResult::kCompleted);
  703. EXPECT_EQ(3, GetCurrentItemsCount());
  704. fake_connection_manager()->SetStatus(
  705. secure_channel::ConnectionManager::Status::kDisconnected);
  706. EXPECT_EQ(0, GetCurrentItemsCount());
  707. }
  708. } // namespace phonehub
  709. } // namespace ash