Snap for 5698743 from bb9649b3fa436ad2a940dcb781deb1f1a09635ba to qt-release

Change-Id: Id4f39b9d0c1d1be7e01d527ba615e69889ae0f89
diff --git a/res/layout/grid_item_category.xml b/res/layout/grid_item_category.xml
index 8d3df82..dbff1a1 100755
--- a/res/layout/grid_item_category.xml
+++ b/res/layout/grid_item_category.xml
@@ -53,6 +53,7 @@
         android:paddingVertical="@dimen/grid_item_category_label_padding"
         android:textColor="@color/category_title_text_color"
         android:textSize="@dimen/abc_text_size_subhead_material"
+        android:textAlignment="viewStart"
         android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title"
         tools:text="Wallpaper category" />
 
diff --git a/res/layout/grid_item_select_wallpaper_header.xml b/res/layout/grid_item_select_wallpaper_header.xml
index 5167abc..faa3dbf 100755
--- a/res/layout/grid_item_select_wallpaper_header.xml
+++ b/res/layout/grid_item_select_wallpaper_header.xml
@@ -20,8 +20,9 @@
     android:layout_marginLeft="@dimen/select_wallpaper_header_margin_left"
     android:layout_marginStart="@dimen/select_wallpaper_header_margin_left"
     android:contentDescription="@string/select_wallpaper_label"
-    android:gravity="center_vertical"
+    android:gravity="start|center_vertical"
     android:text="@string/select_wallpaper_label"
+    android:textAlignment="viewStart"
     android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title"
     android:textColor="@color/select_wallpaper_header_text_color"
     android:textSize="@dimen/abc_text_size_subhead_material"/>
diff --git a/res/layout/grid_item_single_metadata.xml b/res/layout/grid_item_single_metadata.xml
index 8c4e67e..f5dea76 100755
--- a/res/layout/grid_item_single_metadata.xml
+++ b/res/layout/grid_item_single_metadata.xml
@@ -85,6 +85,7 @@
                     android:textSize="@dimen/abc_text_size_subhead_material"
                     android:textAppearance="@style/HeaderTextAppearance"
                     android:textStyle="bold"
+                    android:textAlignment="viewStart"
                     android:ellipsize="end"
                     android:text="@string/wallpaper_destination_both"/>
                 <TextView
@@ -94,6 +95,7 @@
                     android:layout_alignParentStart="true"
                     android:layout_below="@+id/wallpaper_presentation_mode"
                     android:textColor="@color/currently_set_presentation_mode_text_color"
+                    android:textAlignment="viewStart"
                     android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Subtitle"
                     android:textStyle="italic" />
                 <ImageButton
@@ -124,6 +126,7 @@
                     android:layout_marginTop="@dimen/single_metadata_pane_wallpaper_title_margin_top"
                     android:ellipsize="end"
                     android:maxLines="2"
+                    android:textAlignment="viewStart"
                     android:textAppearance="@android:style/TextAppearance.DeviceDefault.Widget.TextView" />
 
                 <TextView
@@ -135,6 +138,7 @@
                     android:layout_marginTop="@dimen/single_metadata_pane_wallpaper_subtitle_margin_top"
                     android:ellipsize="end"
                     android:maxLines="1"
+                    android:textAlignment="viewStart"
                     android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small"
                     android:textColor="@color/currently_set_subtitle_text_color"
                     android:textSize="@dimen/single_metadata_pane_wallpaper_subtitle_text_size" />
@@ -149,6 +153,7 @@
                     android:layout_marginBottom="@dimen/single_metadata_pane_wallpaper_subtitle_margin_bottom"
                     android:ellipsize="end"
                     android:maxLines="1"
+                    android:textAlignment="viewStart"
                     android:textAppearance="@android:style/TextAppearance.DeviceDefault.Small"
                     android:textColor="@color/currently_set_subtitle_text_color"
                     android:textSize="@dimen/single_metadata_pane_wallpaper_subtitle_text_size" />
diff --git a/src/com/android/wallpaper/asset/ContentUriAsset.java b/src/com/android/wallpaper/asset/ContentUriAsset.java
index ed0a368..a240420 100755
--- a/src/com/android/wallpaper/asset/ContentUriAsset.java
+++ b/src/com/android/wallpaper/asset/ContentUriAsset.java
@@ -30,6 +30,7 @@
 
 import com.bumptech.glide.Glide;
 import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
 import com.bumptech.glide.load.engine.GlideException;
 import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
 import com.bumptech.glide.request.RequestListener;
@@ -59,12 +60,43 @@
      * @param context The application's context.
      * @param uri     Content URI locating the asset.
      * @param requestOptions {@link RequestOptions} to be applied when loading the asset.
+     * @param uncached If true, {@link #loadDrawable(Context, ImageView, int)} and
+     * {@link #loadDrawableWithTransition(Context, ImageView, int, DrawableLoadedListener, int)}
+     * will not cache data, and fetch it each time.
      */
-    public ContentUriAsset(Context context, Uri uri, RequestOptions requestOptions) {
+    public ContentUriAsset(Context context, Uri uri, RequestOptions requestOptions,
+                           boolean uncached) {
         mExifOrientation = ExifInterfaceCompat.EXIF_ORIENTATION_UNKNOWN;
         mContext = context.getApplicationContext();
         mUri = uri;
-        mRequestOptions = requestOptions;
+
+        if (uncached) {
+            mRequestOptions = requestOptions.apply(RequestOptions
+                    .diskCacheStrategyOf(DiskCacheStrategy.NONE)
+                    .skipMemoryCache(true));
+        } else {
+            mRequestOptions = requestOptions;
+        }
+    }
+
+    /**
+     * @param context The application's context.
+     * @param uri     Content URI locating the asset.
+     * @param requestOptions {@link RequestOptions} to be applied when loading the asset.
+     */
+    public ContentUriAsset(Context context, Uri uri, RequestOptions requestOptions) {
+        this(context, uri, requestOptions, /* uncached */ false);
+    }
+
+    /**
+     * @param context The application's context.
+     * @param uri     Content URI locating the asset.
+     * @param uncached If true, {@link #loadDrawable(Context, ImageView, int)} and
+     * {@link #loadDrawableWithTransition(Context, ImageView, int, DrawableLoadedListener, int)}
+     * will not cache data, and fetch it each time.
+     */
+    public ContentUriAsset(Context context, Uri uri, boolean uncached) {
+        this(context, uri, RequestOptions.centerCropTransform(), uncached);
     }
 
     /**
@@ -72,9 +104,11 @@
      * @param uri     Content URI locating the asset.
      */
     public ContentUriAsset(Context context, Uri uri) {
-        this(context, uri, RequestOptions.centerCropTransform());
+            this(context, uri, /* uncached */ false);
     }
 
+
+
     @Override
     public void decodeBitmapRegion(final Rect rect, int targetWidth, int targetHeight,
                                    final BitmapReceiver receiver) {
@@ -244,6 +278,10 @@
                 .into(imageView);
     }
 
+    public Uri getUri() {
+        return mUri;
+    }
+
     /**
      * Custom AsyncTask which crops a bitmap region from a larger bitmap.
      */
diff --git a/src/com/android/wallpaper/asset/StreamableAsset.java b/src/com/android/wallpaper/asset/StreamableAsset.java
index d5b27b5..118581d 100755
--- a/src/com/android/wallpaper/asset/StreamableAsset.java
+++ b/src/com/android/wallpaper/asset/StreamableAsset.java
@@ -17,6 +17,7 @@
 
 import android.app.Activity;
 import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
 import android.graphics.BitmapFactory;
 import android.graphics.BitmapRegionDecoder;
 import android.graphics.Matrix;
@@ -26,11 +27,11 @@
 import android.os.AsyncTask;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
+
 import java.io.IOException;
 import java.io.InputStream;
 
-import androidx.annotation.Nullable;
-
 /**
  * Represents Asset types for which bytes can be read directly, allowing for flexible bitmap
  * decoding.
@@ -274,6 +275,7 @@
             }
             options.inSampleSize = BitmapUtils.calculateInSampleSize(
                     rawDimensions.x, rawDimensions.y, mTargetWidth, mTargetHeight);
+            options.inPreferredConfig = Config.HARDWARE;
 
             Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
             closeInputStream(
diff --git a/src/com/android/wallpaper/asset/WallpaperGlideModule.java b/src/com/android/wallpaper/asset/WallpaperGlideModule.java
index 3572e00..6a5e560 100755
--- a/src/com/android/wallpaper/asset/WallpaperGlideModule.java
+++ b/src/com/android/wallpaper/asset/WallpaperGlideModule.java
@@ -8,12 +8,15 @@
 import com.android.wallpaper.asset.NexusStaticAssetLoader.NexusStaticAssetLoaderFactory;
 import com.android.wallpaper.asset.ResourceAssetLoader.ResourceAssetLoaderFactory;
 import com.android.wallpaper.asset.WallpaperModelLoader.WallpaperModelLoaderFactory;
+
 import com.bumptech.glide.Glide;
 import com.bumptech.glide.GlideBuilder;
 import com.bumptech.glide.Registry;
+import com.bumptech.glide.load.DecodeFormat;
 import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
 import com.bumptech.glide.load.engine.cache.MemorySizeCalculator;
 import com.bumptech.glide.module.GlideModule;
+import com.bumptech.glide.request.RequestOptions;
 
 import java.io.InputStream;
 
@@ -40,6 +43,8 @@
                 .setMemoryCacheScreens(1.2f)
                 .build();
         builder.setMemorySizeCalculator(calculator);
+        builder.setDefaultRequestOptions(
+                new RequestOptions().format(DecodeFormat.PREFER_ARGB_8888));
     }
 
     @Override
diff --git a/src/com/android/wallpaper/model/CurrentWallpaperInfoVN.java b/src/com/android/wallpaper/model/CurrentWallpaperInfoVN.java
index eafbec9..e44e717 100755
--- a/src/com/android/wallpaper/model/CurrentWallpaperInfoVN.java
+++ b/src/com/android/wallpaper/model/CurrentWallpaperInfoVN.java
@@ -21,6 +21,9 @@
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
+import androidx.annotation.DrawableRes;
+import androidx.annotation.StringRes;
+
 import com.android.wallpaper.asset.Asset;
 import com.android.wallpaper.asset.BuiltInWallpaperAsset;
 import com.android.wallpaper.asset.CurrentWallpaperAssetVN;
@@ -35,9 +38,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import androidx.annotation.DrawableRes;
-import androidx.annotation.StringRes;
-
 /**
  * Represents the currently set wallpaper on N+ devices. Should not be used to set a new wallpaper.
  */
@@ -134,6 +134,10 @@
         return mActionLabelRes != 0 ? mActionLabelRes : WallpaperInfo.getDefaultActionLabel();
     }
 
+    public int getWallpaperManagerFlag() {
+        return mWallpaperManagerFlag;
+    }
+
     /**
      * Constructs and returns an Asset instance representing the currently-set wallpaper asset.
      */
diff --git a/src/com/android/wallpaper/model/ImageWallpaperInfo.java b/src/com/android/wallpaper/model/ImageWallpaperInfo.java
index fcc1276..e4e96ae 100755
--- a/src/com/android/wallpaper/model/ImageWallpaperInfo.java
+++ b/src/com/android/wallpaper/model/ImageWallpaperInfo.java
@@ -22,6 +22,8 @@
 import android.os.Parcelable;
 import android.util.Log;
 
+import androidx.exifinterface.media.ExifInterface;
+
 import com.android.wallpaper.R;
 import com.android.wallpaper.asset.Asset;
 import com.android.wallpaper.asset.ContentUriAsset;
@@ -33,8 +35,6 @@
 import java.util.Date;
 import java.util.List;
 
-import androidx.exifinterface.media.ExifInterface;
-
 /**
  * Represents a wallpaper image from the system's image picker.
  */
@@ -61,12 +61,18 @@
     };
     private Uri mUri;
     private ContentUriAsset mAsset;
+    private boolean mIsAssetUncached;
 
     public ImageWallpaperInfo(Uri uri) {
         mUri = uri;
     }
 
-    private ImageWallpaperInfo(Parcel in) {
+    public ImageWallpaperInfo(Uri uri, boolean uncachedAsset) {
+        mUri = uri;
+        mIsAssetUncached = uncachedAsset;
+    }
+
+    protected ImageWallpaperInfo(Parcel in) {
         mUri = Uri.parse(in.readString());
     }
 
@@ -136,9 +142,17 @@
 
     @Override
     public Asset getAsset(Context context) {
-        if (mAsset == null) {
-            mAsset = new ContentUriAsset(context, mUri);
+        if (mIsAssetUncached) {
+            mAsset = new ContentUriAsset(
+                    context,
+                    mUri,
+                    /* uncached */ true);
+        } else {
+            if (mAsset == null) {
+                mAsset = new ContentUriAsset(context, mUri);
+            }
         }
+
         return mAsset;
     }
 
diff --git a/src/com/android/wallpaper/model/WallpaperMetadata.java b/src/com/android/wallpaper/model/WallpaperMetadata.java
index 22c1044..cd24796 100755
--- a/src/com/android/wallpaper/model/WallpaperMetadata.java
+++ b/src/com/android/wallpaper/model/WallpaperMetadata.java
@@ -17,11 +17,12 @@
 
 import android.app.WallpaperInfo;
 
-import java.util.List;
-
 import androidx.annotation.DrawableRes;
+import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
+import java.util.List;
+
 /**
  * Lightweight wrapper for user-facing wallpaper metadata.
  */
@@ -30,6 +31,7 @@
     private final List<String> mAttributions;
     private final String mActionUrl;
     private final String mCollectionId;
+    private final String mBackingFileName;
     private final android.app.WallpaperInfo mWallpaperComponent;
     @StringRes private final int mActionLabelRes;
     @DrawableRes private final int mActionIconRes;
@@ -37,12 +39,14 @@
     public WallpaperMetadata(List<String> attributions, String actionUrl,
                              @StringRes int actionLabelRes,
                              @DrawableRes int actionIconRes, String collectionId,
+                             String backingFileName,
                              android.app.WallpaperInfo wallpaperComponent) {
         mAttributions = attributions;
         mActionUrl = actionUrl;
         mActionLabelRes = actionLabelRes;
         mActionIconRes = actionIconRes;
         mCollectionId = collectionId;
+        mBackingFileName = backingFileName;
         mWallpaperComponent = wallpaperComponent;
     }
 
@@ -84,6 +88,15 @@
     }
 
     /**
+     * Returns the name of a private file corresponding to a copy of the full image used as
+     * wallpaper if this is a static wallpaper.
+     */
+    @Nullable
+    public String getBackingFileName() {
+        return mBackingFileName;
+    }
+
+    /**
      * Returns the {@link android.app.WallpaperInfo} if a live wallpaper, or null if the metadata
      * describes an image wallpaper.
      */
diff --git a/src/com/android/wallpaper/module/BaseWallpaperInjector.java b/src/com/android/wallpaper/module/BaseWallpaperInjector.java
index 0904227..15ed84b 100755
--- a/src/com/android/wallpaper/module/BaseWallpaperInjector.java
+++ b/src/com/android/wallpaper/module/BaseWallpaperInjector.java
@@ -42,7 +42,7 @@
     private RotatingWallpaperComponentChecker mRotatingWallpaperComponentChecker;
     private FormFactorChecker mFormFactorChecker;
     private PackageStatusNotifier mPackageStatusNotifier;
-    private IndividualPickerFragment mIndividualPickerFragment;
+    private LiveWallpaperInfoFactory mLiveWallpaperInfoFactory;
 
     @Override
     public synchronized BitmapCropper getBitmapCropper() {
@@ -177,8 +177,14 @@
 
     @Override
     public synchronized IndividualPickerFragment getIndividualPickerFragment(String collectionId) {
-        mIndividualPickerFragment = IndividualPickerFragment.newInstance(collectionId);
+        return IndividualPickerFragment.newInstance(collectionId);
+    }
 
-        return mIndividualPickerFragment;
+    @Override
+    public LiveWallpaperInfoFactory getLiveWallpaperInfoFactory(Context context) {
+        if (mLiveWallpaperInfoFactory == null) {
+            mLiveWallpaperInfoFactory = new DefaultLiveWallpaperInfoFactory();
+        }
+        return mLiveWallpaperInfoFactory;
     }
 }
diff --git a/src/com/android/wallpaper/module/DefaultCategoryProvider.java b/src/com/android/wallpaper/module/DefaultCategoryProvider.java
index 721ccf1..ee7b0cb 100755
--- a/src/com/android/wallpaper/module/DefaultCategoryProvider.java
+++ b/src/com/android/wallpaper/module/DefaultCategoryProvider.java
@@ -75,7 +75,7 @@
             mFetchedCategories = false;
         }
 
-        doFetch(receiver);
+        doFetch(receiver, forceRefresh);
     }
 
     @Override
@@ -103,7 +103,7 @@
         return null;
     }
 
-    protected void doFetch(final CategoryReceiver receiver) {
+    protected void doFetch(final CategoryReceiver receiver, boolean forceRefresh) {
         CategoryReceiver delegatingReceiver = new CategoryReceiver() {
             @Override
             public void onCategoryReceived(Category category) {
diff --git a/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java b/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
index f4fb4ea..c74f9b2 100755
--- a/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
+++ b/src/com/android/wallpaper/module/DefaultCurrentWallpaperInfoFactory.java
@@ -23,9 +23,7 @@
 import com.android.wallpaper.model.CurrentWallpaperInfoVN;
 import com.android.wallpaper.model.LiveWallpaperInfo;
 import com.android.wallpaper.model.WallpaperInfo;
-import com.android.wallpaper.model.WallpaperMetadata;
 import com.android.wallpaper.module.WallpaperPreferences.PresentationMode;
-import com.android.wallpaper.module.WallpaperRefresher.RefreshListener;
 
 import androidx.annotation.Nullable;
 
@@ -35,9 +33,10 @@
  */
 public class DefaultCurrentWallpaperInfoFactory implements CurrentWallpaperInfoFactory {
 
-    private Context mAppContext;
-    private WallpaperRefresher mWallpaperRefresher;
-    private LiveWallpaperStatusChecker mLiveWallpaperStatusChecker;
+    private final Context mAppContext;
+    private final WallpaperRefresher mWallpaperRefresher;
+    private final LiveWallpaperStatusChecker mLiveWallpaperStatusChecker;
+    private final LiveWallpaperInfoFactory mLiveWallpaperInfoFactory;
 
     // Cached copies of the currently-set WallpaperInfo(s) and presentation mode.
     private WallpaperInfo mHomeWallpaper;
@@ -48,9 +47,11 @@
 
     public DefaultCurrentWallpaperInfoFactory(Context context) {
         mAppContext = context.getApplicationContext();
-        mWallpaperRefresher = InjectorProvider.getInjector().getWallpaperRefresher(mAppContext);
+        Injector injector = InjectorProvider.getInjector();
+        mWallpaperRefresher = injector.getWallpaperRefresher(mAppContext);
         mLiveWallpaperStatusChecker =
-                InjectorProvider.getInjector().getLiveWallpaperStatusChecker(mAppContext);
+                injector.getLiveWallpaperStatusChecker(mAppContext);
+        mLiveWallpaperInfoFactory = injector.getLiveWallpaperInfoFactory(mAppContext);
     }
 
     @Override
@@ -69,54 +70,52 @@
             mLockWallpaper = null;
         }
 
-        mWallpaperRefresher.refresh(new RefreshListener() {
-            @Override
-            public void onRefreshed(WallpaperMetadata homeWallpaperMetadata,
-                                    @Nullable WallpaperMetadata lockWallpaperMetadata,
-                                    @PresentationMode int presentationMode) {
+        mWallpaperRefresher.refresh(
+                (homeWallpaperMetadata, lockWallpaperMetadata, presentationMode) -> {
 
-                WallpaperInfo homeWallpaper;
+                    WallpaperInfo homeWallpaper;
 
-                if (homeWallpaperMetadata.getWallpaperComponent() == null
-                        || mLiveWallpaperStatusChecker.isNoBackupImageWallpaperSet()) { // Image wallpaper
-                    if (BuildCompat.isAtLeastN()) {
-                        homeWallpaper = new CurrentWallpaperInfoVN(
-                                homeWallpaperMetadata.getAttributions(),
-                                homeWallpaperMetadata.getActionUrl(),
-                                homeWallpaperMetadata.getActionLabelRes(),
-                                homeWallpaperMetadata.getActionIconRes(),
-                                homeWallpaperMetadata.getCollectionId(),
-                                WallpaperManagerCompat.FLAG_SYSTEM);
-                    } else {
-                        homeWallpaper = new CurrentWallpaperInfoV16(
-                                homeWallpaperMetadata.getAttributions(),
-                                homeWallpaperMetadata.getActionUrl(),
-                                homeWallpaperMetadata.getActionLabelRes(),
-                                homeWallpaperMetadata.getActionIconRes(),
-                                homeWallpaperMetadata.getCollectionId());
+                    if (homeWallpaperMetadata.getWallpaperComponent() == null
+                            || mLiveWallpaperStatusChecker.isNoBackupImageWallpaperSet()) {
+                        // Image wallpaper
+                        if (BuildCompat.isAtLeastN()) {
+                            homeWallpaper = new CurrentWallpaperInfoVN(
+                                    homeWallpaperMetadata.getAttributions(),
+                                    homeWallpaperMetadata.getActionUrl(),
+                                    homeWallpaperMetadata.getActionLabelRes(),
+                                    homeWallpaperMetadata.getActionIconRes(),
+                                    homeWallpaperMetadata.getCollectionId(),
+                                    WallpaperManagerCompat.FLAG_SYSTEM);
+                        } else {
+                            homeWallpaper = new CurrentWallpaperInfoV16(
+                                    homeWallpaperMetadata.getAttributions(),
+                                    homeWallpaperMetadata.getActionUrl(),
+                                    homeWallpaperMetadata.getActionLabelRes(),
+                                    homeWallpaperMetadata.getActionIconRes(),
+                                    homeWallpaperMetadata.getCollectionId());
+                        }
+                    } else { // Live wallpaper
+                        homeWallpaper = mLiveWallpaperInfoFactory.getLiveWallpaperInfo(
+                                homeWallpaperMetadata.getWallpaperComponent());
                     }
-                } else { // Live wallpaper
-                    homeWallpaper = new LiveWallpaperInfo(homeWallpaperMetadata.getWallpaperComponent());
-                }
 
-                WallpaperInfo lockWallpaper = null;
+                    WallpaperInfo lockWallpaper = null;
 
-                if (lockWallpaperMetadata != null) {
-                    lockWallpaper = new CurrentWallpaperInfoVN(
-                            lockWallpaperMetadata.getAttributions(),
-                            lockWallpaperMetadata.getActionUrl(),
-                            lockWallpaperMetadata.getActionLabelRes(),
-                            lockWallpaperMetadata.getActionIconRes(),
-                            lockWallpaperMetadata.getCollectionId(),
-                            WallpaperManagerCompat.FLAG_LOCK);
-                }
+                    if (lockWallpaperMetadata != null) {
+                        lockWallpaper = new CurrentWallpaperInfoVN(
+                                lockWallpaperMetadata.getAttributions(),
+                                lockWallpaperMetadata.getActionUrl(),
+                                lockWallpaperMetadata.getActionLabelRes(),
+                                lockWallpaperMetadata.getActionIconRes(),
+                                lockWallpaperMetadata.getCollectionId(),
+                                WallpaperManagerCompat.FLAG_LOCK);
+                    }
 
-                mHomeWallpaper = homeWallpaper;
-                mLockWallpaper = lockWallpaper;
-                mPresentationMode = presentationMode;
+                    mHomeWallpaper = homeWallpaper;
+                    mLockWallpaper = lockWallpaper;
+                    mPresentationMode = presentationMode;
 
-                callback.onWallpaperInfoCreated(homeWallpaper, lockWallpaper, presentationMode);
-            }
-        });
+                    callback.onWallpaperInfoCreated(homeWallpaper, lockWallpaper, presentationMode);
+                });
     }
 }
diff --git a/src/com/android/wallpaper/module/DefaultLiveWallpaperInfoFactory.java b/src/com/android/wallpaper/module/DefaultLiveWallpaperInfoFactory.java
new file mode 100644
index 0000000..4a06ce5
--- /dev/null
+++ b/src/com/android/wallpaper/module/DefaultLiveWallpaperInfoFactory.java
@@ -0,0 +1,16 @@
+package com.android.wallpaper.module;
+
+import com.android.wallpaper.model.LiveWallpaperInfo;
+import com.android.wallpaper.model.WallpaperInfo;
+
+/**
+ * Default implementation of {@link LiveWallpaperInfoFactory} that just creates
+ * {@link LiveWallpaperInfo}.
+ */
+public class DefaultLiveWallpaperInfoFactory implements LiveWallpaperInfoFactory {
+
+    @Override
+    public WallpaperInfo getLiveWallpaperInfo(android.app.WallpaperInfo info) {
+        return new LiveWallpaperInfo(info);
+    }
+}
diff --git a/src/com/android/wallpaper/module/DefaultWallpaperPreferences.java b/src/com/android/wallpaper/module/DefaultWallpaperPreferences.java
index bd017ac..319276b 100755
--- a/src/com/android/wallpaper/module/DefaultWallpaperPreferences.java
+++ b/src/com/android/wallpaper/module/DefaultWallpaperPreferences.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.annotation.Nullable;
@@ -26,6 +27,7 @@
 import org.json.JSONArray;
 import org.json.JSONException;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -175,6 +177,19 @@
     }
 
     @Override
+    @Nullable
+    public String getHomeWallpaperBackingFileName() {
+        return mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_BACKING_FILE,
+                null);
+    }
+
+    @Override
+    public void setHomeWallpaperBackingFileName(String fileName) {
+        mSharedPrefs.edit().putString(
+                WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_BACKING_FILE, fileName).apply();
+    }
+
+    @Override
     public long getHomeWallpaperHashCode() {
         return mSharedPrefs.getLong(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_HASH_CODE, 0);
     }
@@ -187,6 +202,10 @@
 
     @Override
     public void clearHomeWallpaperMetadata() {
+        String homeWallpaperBackingFileName = getHomeWallpaperBackingFileName();
+        if (!TextUtils.isEmpty(homeWallpaperBackingFileName)) {
+            new File(homeWallpaperBackingFileName).delete();
+        }
         mSharedPrefs.edit()
                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_1)
                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_ATTRIB_2)
@@ -199,6 +218,7 @@
                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_MANAGER_ID)
                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_PACKAGE_NAME)
                 .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_REMOTE_ID)
+                .remove(WallpaperPreferenceKeys.KEY_HOME_WALLPAPER_BACKING_FILE)
                 .apply();
     }
 
@@ -309,6 +329,19 @@
     }
 
     @Override
+    @Nullable
+    public String getLockWallpaperBackingFileName() {
+        return mSharedPrefs.getString(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_BACKING_FILE,
+                null);
+    }
+
+    @Override
+    public void setLockWallpaperBackingFileName(String fileName) {
+        mSharedPrefs.edit().putString(
+                WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_BACKING_FILE, fileName).apply();
+    }
+
+    @Override
     public int getLockWallpaperId() {
         return mSharedPrefs.getInt(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_MANAGER_ID, 0);
     }
@@ -333,6 +366,10 @@
 
     @Override
     public void clearLockWallpaperMetadata() {
+        String lockWallpaperBackingFileName = getLockWallpaperBackingFileName();
+        if (!TextUtils.isEmpty(lockWallpaperBackingFileName)) {
+            new File(lockWallpaperBackingFileName).delete();
+        }
         mSharedPrefs.edit()
                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_1)
                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ATTRIB_2)
@@ -342,6 +379,7 @@
                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_ACTION_ICON_RES)
                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_HASH_CODE)
                 .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_MANAGER_ID)
+                .remove(WallpaperPreferenceKeys.KEY_LOCK_WALLPAPER_BACKING_FILE)
                 .apply();
     }
 
diff --git a/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java b/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
index b5dc7bf..c97d2b9 100755
--- a/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
+++ b/src/com/android/wallpaper/module/DefaultWallpaperRefresher.java
@@ -116,6 +116,7 @@
                         mWallpaperPreferences.getHomeWallpaperActionLabelRes(),
                         mWallpaperPreferences.getHomeWallpaperActionIconRes(),
                         mWallpaperPreferences.getHomeWallpaperCollectionId(),
+                        mWallpaperPreferences.getHomeWallpaperBackingFileName(),
                         mWallpaperManager.getWallpaperInfo()));
                 return wallpaperMetadatas;
             }
@@ -131,6 +132,7 @@
                     mWallpaperPreferences.getHomeWallpaperActionLabelRes(),
                     mWallpaperPreferences.getHomeWallpaperActionIconRes(),
                     mWallpaperPreferences.getHomeWallpaperCollectionId(),
+                    mWallpaperPreferences.getHomeWallpaperBackingFileName(),
                     mWallpaperManager.getWallpaperInfo()));
 
             wallpaperMetadatas.add(new WallpaperMetadata(
@@ -139,6 +141,7 @@
                     mWallpaperPreferences.getLockWallpaperActionLabelRes(),
                     mWallpaperPreferences.getLockWallpaperActionIconRes(),
                     mWallpaperPreferences.getLockWallpaperCollectionId(),
+                    mWallpaperPreferences.getLockWallpaperBackingFileName(),
                     null /* wallpaperComponent */));
 
             return wallpaperMetadatas;
diff --git a/src/com/android/wallpaper/module/Injector.java b/src/com/android/wallpaper/module/Injector.java
index 746917e..6402496 100755
--- a/src/com/android/wallpaper/module/Injector.java
+++ b/src/com/android/wallpaper/module/Injector.java
@@ -81,4 +81,6 @@
     PackageStatusNotifier getPackageStatusNotifier(Context context);
 
     IndividualPickerFragment getIndividualPickerFragment(String collectionId);
+
+    LiveWallpaperInfoFactory getLiveWallpaperInfoFactory(Context context);
 }
diff --git a/src/com/android/wallpaper/module/LiveWallpaperInfoFactory.java b/src/com/android/wallpaper/module/LiveWallpaperInfoFactory.java
new file mode 100644
index 0000000..0c9bfee
--- /dev/null
+++ b/src/com/android/wallpaper/module/LiveWallpaperInfoFactory.java
@@ -0,0 +1,12 @@
+package com.android.wallpaper.module;
+
+import com.android.wallpaper.model.LiveWallpaperInfo;
+import com.android.wallpaper.model.WallpaperInfo;
+
+/**
+ * Interface for factories which construct {@link WallpaperInfo} objects for LiveWallpapers.
+ */
+public interface LiveWallpaperInfoFactory {
+
+    public WallpaperInfo getLiveWallpaperInfo(android.app.WallpaperInfo info);
+}
diff --git a/src/com/android/wallpaper/module/NoOpUserEventLogger.java b/src/com/android/wallpaper/module/NoOpUserEventLogger.java
index 1d780fe..b64beaf 100755
--- a/src/com/android/wallpaper/module/NoOpUserEventLogger.java
+++ b/src/com/android/wallpaper/module/NoOpUserEventLogger.java
@@ -23,7 +23,7 @@
 public class NoOpUserEventLogger implements UserEventLogger {
 
     @Override
-    public void logResumed() {
+    public void logResumed(boolean provisioned, boolean wallpaper) {
 
     }
 
diff --git a/src/com/android/wallpaper/module/UserEventLogger.java b/src/com/android/wallpaper/module/UserEventLogger.java
index 5952396..72e127c 100755
--- a/src/com/android/wallpaper/module/UserEventLogger.java
+++ b/src/com/android/wallpaper/module/UserEventLogger.java
@@ -44,7 +44,7 @@
     int DAILY_WALLPAPER_METADATA_FAILURE_SERVER_ERROR = 3;
     int DAILY_WALLPAPER_METADATA_FAILURE_TIMEOUT = 4;
 
-    void logResumed();
+    void logResumed(boolean provisioned, boolean wallpaper);
 
     void logStopped();
 
diff --git a/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java b/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
index 9f7acbf..f63506f 100755
--- a/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
+++ b/src/com/android/wallpaper/module/WallpaperPreferenceKeys.java
@@ -33,6 +33,7 @@
     public static final String KEY_HOME_WALLPAPER_MANAGER_ID = "home_wallpaper_id";
     public static final String KEY_HOME_WALLPAPER_PACKAGE_NAME = "home_wallpaper_package_name";
     public static final String KEY_HOME_WALLPAPER_REMOTE_ID = "home_wallpaper_remote_id";
+    public static final String KEY_HOME_WALLPAPER_BACKING_FILE = "home_wallpaper_backing_file";
 
     public static final String KEY_LOCK_WALLPAPER_ATTRIB_1 = "lock_wallpaper_attribution_line_1";
     public static final String KEY_LOCK_WALLPAPER_ATTRIB_2 = "lock_wallpaper_attribution_line_2";
@@ -43,6 +44,7 @@
     public static final String KEY_LOCK_WALLPAPER_HASH_CODE = "lock_wallpaper_hash_code";
     public static final String KEY_LOCK_WALLPAPER_COLLECTION_ID = "lock_wallpaper_collection_id";
     public static final String KEY_LOCK_WALLPAPER_MANAGER_ID = "lock_wallpaper_id";
+    public static final String KEY_LOCK_WALLPAPER_BACKING_FILE = "lock_wallpaper_backing_file";
 
     public static final String KEY_DAILY_ROTATION_TIMESTAMPS = "daily_rotation_timestamps";
     public static final String KEY_DAILY_WALLPAPER_ENABLED_TIMESTAMP =
diff --git a/src/com/android/wallpaper/module/WallpaperPreferences.java b/src/com/android/wallpaper/module/WallpaperPreferences.java
index aa964cd..f009f59 100755
--- a/src/com/android/wallpaper/module/WallpaperPreferences.java
+++ b/src/com/android/wallpaper/module/WallpaperPreferences.java
@@ -18,11 +18,11 @@
 import android.annotation.TargetApi;
 import android.os.Build;
 
-import java.util.List;
-
 import androidx.annotation.IntDef;
 import androidx.annotation.Nullable;
 
+import java.util.List;
+
 /**
  * Interface for persisting and retrieving wallpaper specific preferences.
  */
@@ -108,6 +108,16 @@
     void setHomeWallpaperCollectionId(String collectionId);
 
     /**
+     * Returns the home wallpaper's backing file name if there's one or null.
+     */
+    String getHomeWallpaperBackingFileName();
+
+    /**
+     * Sets the home wallpaper's backing file name
+     */
+    void setHomeWallpaperBackingFileName(String fileName);
+
+    /**
      * Removes all home metadata from SharedPreferences.
      */
     void clearHomeWallpaperMetadata();
@@ -197,6 +207,16 @@
     void setLockWallpaperCollectionId(String collectionId);
 
     /**
+     * Returns the home wallpaper's backing file name if there's one or null.
+     */
+    String getLockWallpaperBackingFileName();
+
+    /**
+     * Sets the home wallpaper's backing file name
+     */
+    void setLockWallpaperBackingFileName(String fileName);
+
+    /**
      * Returns the lock screen attributions as a list.
      */
     List<String> getLockWallpaperAttributions();
diff --git a/src/com/android/wallpaper/picker/TopLevelPickerActivity.java b/src/com/android/wallpaper/picker/TopLevelPickerActivity.java
index 42e9081..ac6a13b 100755
--- a/src/com/android/wallpaper/picker/TopLevelPickerActivity.java
+++ b/src/com/android/wallpaper/picker/TopLevelPickerActivity.java
@@ -28,6 +28,7 @@
 import android.os.Build.VERSION;
 import android.os.Build.VERSION_CODES;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -185,7 +186,10 @@
     @Override
     protected void onResume() {
         super.onResume();
-        mUserEventLogger.logResumed();
+        boolean provisioned = Settings.Global.getInt(getContentResolver(),
+                Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+
+        mUserEventLogger.logResumed(provisioned, true);
         // Show the staged 'load wallpaper' or 'set wallpaper' error dialog fragments if there is one
         // that was unable to be shown earlier when this fragment's hosting activity didn't allow
         // committing fragment transactions.
diff --git a/src/com/android/wallpaper/picker/individual/IndividualPickerActivity.java b/src/com/android/wallpaper/picker/individual/IndividualPickerActivity.java
index 6c05983..1f5dc99 100755
--- a/src/com/android/wallpaper/picker/individual/IndividualPickerActivity.java
+++ b/src/com/android/wallpaper/picker/individual/IndividualPickerActivity.java
@@ -108,6 +108,7 @@
         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 
         toolbar.getNavigationIcon().setTint(getColor(R.color.toolbar_icon_color));
+        toolbar.getNavigationIcon().setAutoMirrored(true);
 
         getWindow().getDecorView().setSystemUiVisibility(
                 getWindow().getDecorView().getSystemUiVisibility()