ambient_photo_controller.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // Copyright 2019 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. #ifndef ASH_AMBIENT_AMBIENT_PHOTO_CONTROLLER_H_
  5. #define ASH_AMBIENT_AMBIENT_PHOTO_CONTROLLER_H_
  6. #include <memory>
  7. #include <ostream>
  8. #include <string>
  9. #include <utility>
  10. #include "ash/ambient/ambient_constants.h"
  11. #include "ash/ambient/ambient_photo_cache.h"
  12. #include "ash/ambient/model/ambient_backend_model.h"
  13. #include "ash/ambient/model/ambient_photo_config.h"
  14. #include "ash/ambient/model/ambient_topic_queue.h"
  15. #include "ash/ambient/ui/ambient_view_delegate.h"
  16. #include "ash/ash_export.h"
  17. #include "ash/public/cpp/ambient/ambient_backend_controller.h"
  18. #include "ash/public/cpp/ambient/proto/photo_cache_entry.pb.h"
  19. #include "base/callback_forward.h"
  20. #include "base/memory/scoped_refptr.h"
  21. #include "base/memory/weak_ptr.h"
  22. #include "base/scoped_observation.h"
  23. #include "base/timer/timer.h"
  24. #include "net/base/backoff_entry.h"
  25. #include "services/network/public/cpp/simple_url_loader.h"
  26. #include "third_party/abseil-cpp/absl/types/optional.h"
  27. namespace gfx {
  28. class ImageSkia;
  29. } // namespace gfx
  30. namespace ash {
  31. class AmbientClient;
  32. class AmbientAccessTokenController;
  33. // Class to handle photos in ambient mode.
  34. //
  35. // Terminology:
  36. //
  37. // Topic - A primary and optional related photo specified by the IMAX server.
  38. //
  39. // Fetch Topics - Request new topics from the IMAX server. After they're
  40. // fetched, the controller just has urls for the primary/optional
  41. // photos in each returned topic.
  42. //
  43. // Download Topic - Download the encoded primary/related photos from their
  44. // corresponding urls.
  45. //
  46. // Save Topic - Write the topic's encoded photos to disk for future re-use.
  47. // Helpful in future cases where ambient mode starts and there's no
  48. // internet.
  49. //
  50. // Load Topic - Read a previously saved topic's encoded photos from disk.
  51. //
  52. // Decode Topic - Decode the topic's photos and commit them to the
  53. // AmbientBackendModel.
  54. //
  55. // Prepare Topic - A term that aggregates all of the steps above:
  56. // 1) Either a) fetch/download/save new topic or b) load existing topic
  57. // 2) Decode topic and commit to the model.
  58. //
  59. // Topic Set - A group of topics for the UI to display in one cycle, capped by
  60. // |AmbientPhotoConfig.topic_set_size|.
  61. //
  62. // The controller's state machine:
  63. //
  64. // kInactive
  65. // |
  66. // |
  67. // v
  68. // kPreparingNextTopicSet <-----
  69. // | |
  70. // | |
  71. // v |
  72. // kWaitingForNextMarker -------
  73. //
  74. // kInactive:
  75. // The controller is idle, and the model has no decoded topics in it. This is
  76. // the initial state when the controller is constructed. Although not
  77. // illustrated above, the controller can transition to this state from any of
  78. // the other states via a call to StopScreenUpdate().
  79. //
  80. //
  81. // kPreparingNextTopicSet (a.k.a. "refreshing" the model's topics):
  82. // The very first time this state is reached, the UI has not started rendering
  83. // yet, and the controller is preparing initial sets of topics. The
  84. // AmbientPhotoConfig dictates how many sets to prepare initially. This state is
  85. // initially triggered by a call to StartScreenUpdate(), and it ends when
  86. // AmbientBackendModel::ImagesReady() is true.
  87. //
  88. // kWaitingForNextMarker:
  89. // The UI is rendering the decoded topics currently in the model, and the
  90. // controller is idle. It's waiting for the right marker(s) to be hit in the UI
  91. // before it becomes active and starts preparing the next set of topics.
  92. //
  93. // kPreparingNextTopicSet (again):
  94. // A target marker has been hit, and the controller immediately starts preparing
  95. // the next set of topics. Unlike the first time this state was hit, there
  96. // is only ever 1 topic set prepared, and the UI is rendering while the topics
  97. // are being prepared. After the topic set is completely prepared, the
  98. // controller goes back to WAITING_FOR_NEXT_MARKER. If another target marker is
  99. // received while the controller is still preparing a topic set, the controller
  100. // will simply reset its internal "counter" to 0 and start preparing a brand new
  101. // set.
  102. class ASH_EXPORT AmbientPhotoController : public AmbientViewDelegateObserver {
  103. public:
  104. AmbientPhotoController(AmbientClient& ambient_client,
  105. AmbientAccessTokenController& access_token_controller,
  106. AmbientViewDelegate& view_delegate,
  107. AmbientPhotoConfig photo_config);
  108. AmbientPhotoController(const AmbientPhotoController&) = delete;
  109. AmbientPhotoController& operator=(const AmbientPhotoController&) = delete;
  110. ~AmbientPhotoController() override;
  111. // Start/stop updating the screen contents.
  112. // We need different logics to update photos and weather info because they
  113. // have different refreshing intervals.
  114. void StartScreenUpdate(
  115. std::unique_ptr<AmbientTopicQueue::Delegate> topic_queue_delegate);
  116. void StopScreenUpdate();
  117. bool IsScreenUpdateActive() const;
  118. AmbientBackendModel* ambient_backend_model() {
  119. return &ambient_backend_model_;
  120. }
  121. base::OneShotTimer& backup_photo_refresh_timer_for_testing() {
  122. return backup_photo_refresh_timer_;
  123. }
  124. // AmbientViewDelegateObserver:
  125. void OnMarkerHit(AmbientPhotoConfig::Marker marker) override;
  126. // Clear cache when Settings changes.
  127. void ClearCache();
  128. private:
  129. enum class State { kInactive, kWaitingForNextMarker, kPreparingNextTopicSet };
  130. friend class AmbientAshTestBase;
  131. friend class AmbientPhotoControllerTest;
  132. friend std::ostream& operator<<(std::ostream& os, State state);
  133. // Initialize variables.
  134. void Init(std::unique_ptr<AmbientTopicQueue::Delegate> topic_queue_delegate);
  135. // Requests that the weather controller fetch updated weather info.
  136. void FetchWeather();
  137. void ScheduleFetchBackupImages();
  138. // Download backup cache images.
  139. void FetchBackupImages();
  140. void OnBackupImageFetched(bool success);
  141. void OnTopicsAvailableInQueue(AmbientTopicQueue::WaitResult wait_result);
  142. // Clear temporary image data to prepare next photos.
  143. void ResetImageData();
  144. void ReadPhotoFromTopicQueue();
  145. void TryReadPhotoFromCache();
  146. void OnPhotoCacheReadComplete(::ambient::PhotoCacheEntry cache_entry);
  147. void OnPhotoRawDataDownloaded(bool is_related_image,
  148. base::RepeatingClosure on_done,
  149. std::string&& data);
  150. void OnAllPhotoRawDataDownloaded();
  151. void OnAllPhotoRawDataAvailable(bool from_downloading);
  152. void OnPhotoRawDataSaved(bool from_downloading);
  153. void DecodePhotoRawData(bool from_downloading,
  154. bool is_related_image,
  155. base::RepeatingClosure on_done,
  156. const std::string& data);
  157. void OnPhotoDecoded(bool from_downloading,
  158. bool is_related_image,
  159. base::RepeatingClosure on_done,
  160. const gfx::ImageSkia& image);
  161. void OnAllPhotoDecoded(bool from_downloading,
  162. const std::string& hash);
  163. void set_photo_cache_for_testing(
  164. std::unique_ptr<AmbientPhotoCache> photo_cache) {
  165. photo_cache_ = std::move(photo_cache);
  166. }
  167. AmbientPhotoCache* get_photo_cache_for_testing() {
  168. return photo_cache_.get();
  169. }
  170. void set_backup_photo_cache_for_testing(
  171. std::unique_ptr<AmbientPhotoCache> photo_cache) {
  172. backup_photo_cache_ = std::move(photo_cache);
  173. }
  174. AmbientPhotoCache* get_backup_photo_cache_for_testing() {
  175. return backup_photo_cache_.get();
  176. }
  177. void FetchTopicsForTesting();
  178. void FetchImageForTesting();
  179. void FetchBackupImagesForTesting();
  180. // Kicks off preparation of the next topic.
  181. void StartPreparingNextTopic();
  182. std::unique_ptr<AmbientTopicQueue> ambient_topic_queue_;
  183. AmbientBackendModel ambient_backend_model_;
  184. // The timer to refresh backup cache photos.
  185. base::OneShotTimer backup_photo_refresh_timer_;
  186. // The timer to refresh weather information.
  187. base::RepeatingTimer weather_refresh_timer_;
  188. State state_ = State::kInactive;
  189. // The index of a topic to download.
  190. size_t topic_index_ = 0;
  191. // Current index of cached image to read and display when failure happens.
  192. // The image file of this index may not exist or may not be valid. It will try
  193. // to read from the next cached file by increasing this index by 1.
  194. int cache_index_for_display_ = 0;
  195. // Current index of backup cached image to display when no other cached images
  196. // are available.
  197. size_t backup_cache_index_for_display_ = 0;
  198. // Current index of cached image to save for the latest downloaded photo.
  199. // The write command could fail. This index will increase 1 no matter writing
  200. // successfully or not. But theoretically we could not to change this index if
  201. // failures happen.
  202. int cache_index_for_store_ = 0;
  203. // Cached image may not exist or valid. This is the max times of attempts to
  204. // read cached images.
  205. int retries_to_read_from_cache_ = kMaxNumberOfCachedImages;
  206. int backup_retries_to_read_from_cache_ = 0;
  207. // Backoff to resume fetch images.
  208. net::BackoffEntry resume_fetch_image_backoff_;
  209. std::unique_ptr<AmbientPhotoCache> photo_cache_;
  210. std::unique_ptr<AmbientPhotoCache> backup_photo_cache_;
  211. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  212. // Temporary data store when fetching images and details.
  213. ::ambient::PhotoCacheEntry cache_entry_;
  214. gfx::ImageSkia image_;
  215. gfx::ImageSkia related_image_;
  216. // Tracks the number of topics that have been prepared since the controller
  217. // last transitioned to the |kPreparingNextTopicSet| state.
  218. size_t num_topics_prepared_ = 0;
  219. base::ScopedObservation<AmbientViewDelegate, AmbientViewDelegateObserver>
  220. scoped_view_delegate_observation_{this};
  221. base::WeakPtrFactory<AmbientPhotoController> weak_factory_{this};
  222. };
  223. } // namespace ash
  224. #endif // ASH_AMBIENT_AMBIENT_PHOTO_CONTROLLER_H_