123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- // Copyright 2019 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.
- #ifndef ASH_AMBIENT_AMBIENT_PHOTO_CONTROLLER_H_
- #define ASH_AMBIENT_AMBIENT_PHOTO_CONTROLLER_H_
- #include <memory>
- #include <ostream>
- #include <string>
- #include <utility>
- #include "ash/ambient/ambient_constants.h"
- #include "ash/ambient/ambient_photo_cache.h"
- #include "ash/ambient/model/ambient_backend_model.h"
- #include "ash/ambient/model/ambient_photo_config.h"
- #include "ash/ambient/model/ambient_topic_queue.h"
- #include "ash/ambient/ui/ambient_view_delegate.h"
- #include "ash/ash_export.h"
- #include "ash/public/cpp/ambient/ambient_backend_controller.h"
- #include "ash/public/cpp/ambient/proto/photo_cache_entry.pb.h"
- #include "base/callback_forward.h"
- #include "base/memory/scoped_refptr.h"
- #include "base/memory/weak_ptr.h"
- #include "base/scoped_observation.h"
- #include "base/timer/timer.h"
- #include "net/base/backoff_entry.h"
- #include "services/network/public/cpp/simple_url_loader.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace gfx {
- class ImageSkia;
- } // namespace gfx
- namespace ash {
- class AmbientClient;
- class AmbientAccessTokenController;
- // Class to handle photos in ambient mode.
- //
- // Terminology:
- //
- // Topic - A primary and optional related photo specified by the IMAX server.
- //
- // Fetch Topics - Request new topics from the IMAX server. After they're
- // fetched, the controller just has urls for the primary/optional
- // photos in each returned topic.
- //
- // Download Topic - Download the encoded primary/related photos from their
- // corresponding urls.
- //
- // Save Topic - Write the topic's encoded photos to disk for future re-use.
- // Helpful in future cases where ambient mode starts and there's no
- // internet.
- //
- // Load Topic - Read a previously saved topic's encoded photos from disk.
- //
- // Decode Topic - Decode the topic's photos and commit them to the
- // AmbientBackendModel.
- //
- // Prepare Topic - A term that aggregates all of the steps above:
- // 1) Either a) fetch/download/save new topic or b) load existing topic
- // 2) Decode topic and commit to the model.
- //
- // Topic Set - A group of topics for the UI to display in one cycle, capped by
- // |AmbientPhotoConfig.topic_set_size|.
- //
- // The controller's state machine:
- //
- // kInactive
- // |
- // |
- // v
- // kPreparingNextTopicSet <-----
- // | |
- // | |
- // v |
- // kWaitingForNextMarker -------
- //
- // kInactive:
- // The controller is idle, and the model has no decoded topics in it. This is
- // the initial state when the controller is constructed. Although not
- // illustrated above, the controller can transition to this state from any of
- // the other states via a call to StopScreenUpdate().
- //
- //
- // kPreparingNextTopicSet (a.k.a. "refreshing" the model's topics):
- // The very first time this state is reached, the UI has not started rendering
- // yet, and the controller is preparing initial sets of topics. The
- // AmbientPhotoConfig dictates how many sets to prepare initially. This state is
- // initially triggered by a call to StartScreenUpdate(), and it ends when
- // AmbientBackendModel::ImagesReady() is true.
- //
- // kWaitingForNextMarker:
- // The UI is rendering the decoded topics currently in the model, and the
- // controller is idle. It's waiting for the right marker(s) to be hit in the UI
- // before it becomes active and starts preparing the next set of topics.
- //
- // kPreparingNextTopicSet (again):
- // A target marker has been hit, and the controller immediately starts preparing
- // the next set of topics. Unlike the first time this state was hit, there
- // is only ever 1 topic set prepared, and the UI is rendering while the topics
- // are being prepared. After the topic set is completely prepared, the
- // controller goes back to WAITING_FOR_NEXT_MARKER. If another target marker is
- // received while the controller is still preparing a topic set, the controller
- // will simply reset its internal "counter" to 0 and start preparing a brand new
- // set.
- class ASH_EXPORT AmbientPhotoController : public AmbientViewDelegateObserver {
- public:
- AmbientPhotoController(AmbientClient& ambient_client,
- AmbientAccessTokenController& access_token_controller,
- AmbientViewDelegate& view_delegate,
- AmbientPhotoConfig photo_config);
- AmbientPhotoController(const AmbientPhotoController&) = delete;
- AmbientPhotoController& operator=(const AmbientPhotoController&) = delete;
- ~AmbientPhotoController() override;
- // Start/stop updating the screen contents.
- // We need different logics to update photos and weather info because they
- // have different refreshing intervals.
- void StartScreenUpdate(
- std::unique_ptr<AmbientTopicQueue::Delegate> topic_queue_delegate);
- void StopScreenUpdate();
- bool IsScreenUpdateActive() const;
- AmbientBackendModel* ambient_backend_model() {
- return &ambient_backend_model_;
- }
- base::OneShotTimer& backup_photo_refresh_timer_for_testing() {
- return backup_photo_refresh_timer_;
- }
- // AmbientViewDelegateObserver:
- void OnMarkerHit(AmbientPhotoConfig::Marker marker) override;
- // Clear cache when Settings changes.
- void ClearCache();
- private:
- enum class State { kInactive, kWaitingForNextMarker, kPreparingNextTopicSet };
- friend class AmbientAshTestBase;
- friend class AmbientPhotoControllerTest;
- friend std::ostream& operator<<(std::ostream& os, State state);
- // Initialize variables.
- void Init(std::unique_ptr<AmbientTopicQueue::Delegate> topic_queue_delegate);
- // Requests that the weather controller fetch updated weather info.
- void FetchWeather();
- void ScheduleFetchBackupImages();
- // Download backup cache images.
- void FetchBackupImages();
- void OnBackupImageFetched(bool success);
- void OnTopicsAvailableInQueue(AmbientTopicQueue::WaitResult wait_result);
- // Clear temporary image data to prepare next photos.
- void ResetImageData();
- void ReadPhotoFromTopicQueue();
- void TryReadPhotoFromCache();
- void OnPhotoCacheReadComplete(::ambient::PhotoCacheEntry cache_entry);
- void OnPhotoRawDataDownloaded(bool is_related_image,
- base::RepeatingClosure on_done,
- std::string&& data);
- void OnAllPhotoRawDataDownloaded();
- void OnAllPhotoRawDataAvailable(bool from_downloading);
- void OnPhotoRawDataSaved(bool from_downloading);
- void DecodePhotoRawData(bool from_downloading,
- bool is_related_image,
- base::RepeatingClosure on_done,
- const std::string& data);
- void OnPhotoDecoded(bool from_downloading,
- bool is_related_image,
- base::RepeatingClosure on_done,
- const gfx::ImageSkia& image);
- void OnAllPhotoDecoded(bool from_downloading,
- const std::string& hash);
- void set_photo_cache_for_testing(
- std::unique_ptr<AmbientPhotoCache> photo_cache) {
- photo_cache_ = std::move(photo_cache);
- }
- AmbientPhotoCache* get_photo_cache_for_testing() {
- return photo_cache_.get();
- }
- void set_backup_photo_cache_for_testing(
- std::unique_ptr<AmbientPhotoCache> photo_cache) {
- backup_photo_cache_ = std::move(photo_cache);
- }
- AmbientPhotoCache* get_backup_photo_cache_for_testing() {
- return backup_photo_cache_.get();
- }
- void FetchTopicsForTesting();
- void FetchImageForTesting();
- void FetchBackupImagesForTesting();
- // Kicks off preparation of the next topic.
- void StartPreparingNextTopic();
- std::unique_ptr<AmbientTopicQueue> ambient_topic_queue_;
- AmbientBackendModel ambient_backend_model_;
- // The timer to refresh backup cache photos.
- base::OneShotTimer backup_photo_refresh_timer_;
- // The timer to refresh weather information.
- base::RepeatingTimer weather_refresh_timer_;
- State state_ = State::kInactive;
- // The index of a topic to download.
- size_t topic_index_ = 0;
- // Current index of cached image to read and display when failure happens.
- // The image file of this index may not exist or may not be valid. It will try
- // to read from the next cached file by increasing this index by 1.
- int cache_index_for_display_ = 0;
- // Current index of backup cached image to display when no other cached images
- // are available.
- size_t backup_cache_index_for_display_ = 0;
- // Current index of cached image to save for the latest downloaded photo.
- // The write command could fail. This index will increase 1 no matter writing
- // successfully or not. But theoretically we could not to change this index if
- // failures happen.
- int cache_index_for_store_ = 0;
- // Cached image may not exist or valid. This is the max times of attempts to
- // read cached images.
- int retries_to_read_from_cache_ = kMaxNumberOfCachedImages;
- int backup_retries_to_read_from_cache_ = 0;
- // Backoff to resume fetch images.
- net::BackoffEntry resume_fetch_image_backoff_;
- std::unique_ptr<AmbientPhotoCache> photo_cache_;
- std::unique_ptr<AmbientPhotoCache> backup_photo_cache_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
- // Temporary data store when fetching images and details.
- ::ambient::PhotoCacheEntry cache_entry_;
- gfx::ImageSkia image_;
- gfx::ImageSkia related_image_;
- // Tracks the number of topics that have been prepared since the controller
- // last transitioned to the |kPreparingNextTopicSet| state.
- size_t num_topics_prepared_ = 0;
- base::ScopedObservation<AmbientViewDelegate, AmbientViewDelegateObserver>
- scoped_view_delegate_observation_{this};
- base::WeakPtrFactory<AmbientPhotoController> weak_factory_{this};
- };
- } // namespace ash
- #endif // ASH_AMBIENT_AMBIENT_PHOTO_CONTROLLER_H_
|