blob: 654ec131ff786f0918d111bcb3ec631d9f9539c4 [file] [log] [blame]
Jon Miranda16ea1b12017-12-12 14:52:48 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.wallpaper.picker.individual;
17
18import android.app.Activity;
19import android.app.ProgressDialog;
20import android.content.Context;
Santiago Etchebehereb1854472019-06-06 17:44:54 -070021import android.content.res.Configuration;
Jon Miranda16ea1b12017-12-12 14:52:48 -080022import android.content.res.Resources.NotFoundException;
23import android.graphics.Point;
24import android.graphics.PorterDuff.Mode;
25import android.os.Build.VERSION;
26import android.os.Build.VERSION_CODES;
27import android.os.Bundle;
28import android.os.Handler;
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -070029import android.service.wallpaper.WallpaperService;
Jon Miranda16ea1b12017-12-12 14:52:48 -080030import android.util.Log;
31import android.view.LayoutInflater;
32import android.view.View;
33import android.view.ViewGroup;
34import android.widget.FrameLayout;
35import android.widget.ImageView;
36import android.widget.TextView;
37import android.widget.Toast;
38
Santiago Etchebehereb1854472019-06-06 17:44:54 -070039import androidx.annotation.NonNull;
Santiago Etchebeherefab49612019-01-15 12:22:42 -080040import androidx.fragment.app.DialogFragment;
41import androidx.fragment.app.Fragment;
42import androidx.recyclerview.widget.GridLayoutManager;
43import androidx.recyclerview.widget.RecyclerView;
44import androidx.recyclerview.widget.RecyclerView.OnScrollListener;
45import androidx.recyclerview.widget.RecyclerView.ViewHolder;
46
Jon Miranda16ea1b12017-12-12 14:52:48 -080047import com.android.wallpaper.R;
48import com.android.wallpaper.asset.Asset;
49import com.android.wallpaper.asset.Asset.DrawableLoadedListener;
50import com.android.wallpaper.config.Flags;
51import com.android.wallpaper.model.WallpaperCategory;
52import com.android.wallpaper.model.WallpaperInfo;
53import com.android.wallpaper.model.WallpaperReceiver;
54import com.android.wallpaper.model.WallpaperRotationInitializer;
55import com.android.wallpaper.model.WallpaperRotationInitializer.Listener;
56import com.android.wallpaper.model.WallpaperRotationInitializer.NetworkPreference;
57import com.android.wallpaper.model.WallpaperRotationInitializer.RotationInitializationState;
58import com.android.wallpaper.model.WallpaperRotationInitializer.RotationStateListener;
59import com.android.wallpaper.module.FormFactorChecker;
60import com.android.wallpaper.module.FormFactorChecker.FormFactor;
61import com.android.wallpaper.module.Injector;
62import com.android.wallpaper.module.InjectorProvider;
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -070063import com.android.wallpaper.module.PackageStatusNotifier;
Jon Miranda16ea1b12017-12-12 14:52:48 -080064import com.android.wallpaper.module.RotatingWallpaperComponentChecker;
65import com.android.wallpaper.module.WallpaperChangedNotifier;
66import com.android.wallpaper.module.WallpaperPersister;
67import com.android.wallpaper.module.WallpaperPersister.Destination;
68import com.android.wallpaper.module.WallpaperPreferences;
69import com.android.wallpaper.picker.BaseActivity;
70import com.android.wallpaper.picker.CurrentWallpaperBottomSheetPresenter;
Santiago Etchebeherefab49612019-01-15 12:22:42 -080071import com.android.wallpaper.picker.MyPhotosStarter.MyPhotosStarterProvider;
Jon Miranda16ea1b12017-12-12 14:52:48 -080072import com.android.wallpaper.picker.RotationStarter;
73import com.android.wallpaper.picker.SetWallpaperErrorDialogFragment;
74import com.android.wallpaper.picker.StartRotationDialogFragment;
75import com.android.wallpaper.picker.StartRotationErrorDialogFragment;
76import com.android.wallpaper.picker.WallpapersUiContainer;
77import com.android.wallpaper.picker.individual.SetIndividualHolder.OnSetListener;
78import com.android.wallpaper.util.DiskBasedLogger;
79import com.android.wallpaper.util.TileSizeCalculator;
80import com.android.wallpaper.widget.GridMarginDecoration;
Sunny Goyal8600a3f2018-08-15 12:48:01 -070081
Jon Miranda16ea1b12017-12-12 14:52:48 -080082import com.bumptech.glide.Glide;
83import com.bumptech.glide.MemoryCategory;
84
85import java.util.ArrayList;
86import java.util.Date;
87import java.util.List;
88import java.util.Random;
89
90/**
91 * Displays the Main UI for picking an individual wallpaper image.
92 */
93public class IndividualPickerFragment extends Fragment
94 implements RotationStarter, StartRotationErrorDialogFragment.Listener,
95 CurrentWallpaperBottomSheetPresenter.RefreshListener,
96 SetWallpaperErrorDialogFragment.Listener {
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +080097 /**
98 * Position of a special tile that doesn't belong to an individual wallpaper of the category,
99 * such as "my photos" or "daily rotation".
100 */
101 static final int SPECIAL_FIXED_TILE_ADAPTER_POSITION = 0;
102 static final String ARG_CATEGORY_COLLECTION_ID = "category_collection_id";
103
Jon Miranda16ea1b12017-12-12 14:52:48 -0800104 private static final String TAG = "IndividualPickerFrgmnt";
Jon Miranda16ea1b12017-12-12 14:52:48 -0800105 private static final int UNUSED_REQUEST_CODE = 1;
106 private static final String TAG_START_ROTATION_DIALOG = "start_rotation_dialog";
107 private static final String TAG_START_ROTATION_ERROR_DIALOG = "start_rotation_error_dialog";
108 private static final String PROGRESS_DIALOG_NO_TITLE = null;
109 private static final boolean PROGRESS_DIALOG_INDETERMINATE = true;
110 private static final String TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT =
111 "individual_set_wallpaper_error_dialog";
Santiago Etchebehereb1854472019-06-06 17:44:54 -0700112 private static final String KEY_NIGHT_MODE = "IndividualPickerFragment.NIGHT_MODE";
Jon Miranda16ea1b12017-12-12 14:52:48 -0800113
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800114 WallpaperPreferences mWallpaperPreferences;
115 WallpaperChangedNotifier mWallpaperChangedNotifier;
116 RotatingWallpaperComponentChecker mRotatingWallpaperComponentChecker;
117 RecyclerView mImageGrid;
118 IndividualAdapter mAdapter;
119 WallpaperCategory mCategory;
120 WallpaperRotationInitializer mWallpaperRotationInitializer;
121 List<WallpaperInfo> mWallpapers;
122 Point mTileSizePx;
123 WallpapersUiContainer mWallpapersUiContainer;
124 @FormFactor
125 int mFormFactor;
126 PackageStatusNotifier mPackageStatusNotifier;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800127
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800128 Handler mHandler;
129 Random mRandom;
130
131 WallpaperChangedNotifier.Listener mWallpaperChangedListener =
132 new WallpaperChangedNotifier.Listener() {
133 @Override
134 public void onWallpaperChanged() {
135 if (mFormFactor != FormFactorChecker.FORM_FACTOR_DESKTOP) {
136 return;
137 }
138
139 ViewHolder selectedViewHolder = mImageGrid.findViewHolderForAdapterPosition(
140 mAdapter.mSelectedAdapterPosition);
141
142 // Null remote ID => My Photos wallpaper, so deselect whatever was previously selected.
143 if (mWallpaperPreferences.getHomeWallpaperRemoteId() == null) {
144 if (selectedViewHolder instanceof SelectableHolder) {
145 ((SelectableHolder) selectedViewHolder).setSelectionState(
146 SelectableHolder.SELECTION_STATE_DESELECTED);
147 }
148 } else {
149 mAdapter.updateSelectedTile(mAdapter.mPendingSelectedAdapterPosition);
150 }
151 }
152 };
153 PackageStatusNotifier.Listener mAppStatusListener;
154
Jon Miranda16ea1b12017-12-12 14:52:48 -0800155 private ProgressDialog mProgressDialog;
156 private boolean mTestingMode;
157 private CurrentWallpaperBottomSheetPresenter mCurrentWallpaperBottomSheetPresenter;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800158 private SetIndividualHolder mPendingSetIndividualHolder;
159
160 /**
161 * Staged error dialog fragments that were unable to be shown when the activity didn't allow
162 * committing fragment transactions.
163 */
164 private SetWallpaperErrorDialogFragment mStagedSetWallpaperErrorDialogFragment;
165 private StartRotationErrorDialogFragment mStagedStartRotationErrorDialogFragment;
166
Jon Miranda16ea1b12017-12-12 14:52:48 -0800167 private Runnable mCurrentWallpaperBottomSheetExpandedRunnable;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800168
169 /**
170 * Whether {@code mUpdateDailyWallpaperThumbRunnable} has been run at least once in this
171 * invocation of the fragment.
172 */
173 private boolean mWasUpdateRunnableRun;
174
175 /**
176 * A Runnable which regularly updates the thumbnail for the "Daily wallpapers" tile in desktop
177 * mode.
178 */
179 private Runnable mUpdateDailyWallpaperThumbRunnable = new Runnable() {
180 @Override
181 public void run() {
182 ViewHolder viewHolder = mImageGrid.findViewHolderForAdapterPosition(
183 SPECIAL_FIXED_TILE_ADAPTER_POSITION);
184 if (viewHolder instanceof DesktopRotationHolder) {
185 updateDesktopDailyRotationThumbnail((DesktopRotationHolder) viewHolder);
186 } else { // viewHolder is null
187 // If the rotation tile is unavailable (because user has scrolled down, causing the
188 // ViewHolder to be recycled), schedule the update for some time later. Once user scrolls up
189 // again, the ViewHolder will be re-bound and its thumbnail will be updated.
190 mHandler.postDelayed(mUpdateDailyWallpaperThumbRunnable,
191 DesktopRotationHolder.CROSSFADE_DURATION_MILLIS
192 + DesktopRotationHolder.CROSSFADE_DURATION_PAUSE_MILLIS);
193 }
194 }
195 };
196
Jon Miranda16ea1b12017-12-12 14:52:48 -0800197 public static IndividualPickerFragment newInstance(String collectionId) {
198 Bundle args = new Bundle();
199 args.putString(ARG_CATEGORY_COLLECTION_ID, collectionId);
200
201 IndividualPickerFragment fragment = new IndividualPickerFragment();
202 fragment.setArguments(args);
203 return fragment;
204 }
205
206 private static int getResIdForRotationState(@RotationInitializationState int rotationState) {
207 switch (rotationState) {
208 case WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED:
209 return R.string.daily_refresh_tile_subtitle;
210 case WallpaperRotationInitializer.ROTATION_HOME_ONLY:
211 return R.string.home_screen_message;
212 case WallpaperRotationInitializer.ROTATION_HOME_AND_LOCK:
213 return R.string.home_and_lock_short_label;
214 default:
215 Log.e(TAG, "Unknown rotation intialization state: " + rotationState);
216 return R.string.home_screen_message;
217 }
218 }
219
220 private void updateDesktopDailyRotationThumbnail(DesktopRotationHolder holder) {
221 int wallpapersIndex = mRandom.nextInt(mWallpapers.size());
222 Asset newThumbnailAsset = mWallpapers.get(wallpapersIndex).getThumbAsset(
223 getActivity());
224 holder.updateThumbnail(newThumbnailAsset, new DrawableLoadedListener() {
225 @Override
226 public void onDrawableLoaded() {
227 if (getActivity() == null) {
228 return;
229 }
230
231 // Schedule the next update of the thumbnail.
232 int delayMillis = DesktopRotationHolder.CROSSFADE_DURATION_MILLIS
233 + DesktopRotationHolder.CROSSFADE_DURATION_PAUSE_MILLIS;
234 mHandler.postDelayed(mUpdateDailyWallpaperThumbRunnable, delayMillis);
235 }
236 });
237 }
238
239 @Override
240 public void onCreate(Bundle savedInstanceState) {
241 super.onCreate(savedInstanceState);
242
243 Injector injector = InjectorProvider.getInjector();
244 Context appContext = getContext().getApplicationContext();
245 mWallpaperPreferences = injector.getPreferences(appContext);
246
247 mWallpaperChangedNotifier = WallpaperChangedNotifier.getInstance();
248 mWallpaperChangedNotifier.registerListener(mWallpaperChangedListener);
249
250 mRotatingWallpaperComponentChecker = injector.getRotatingWallpaperComponentChecker();
251
252 mFormFactor = injector.getFormFactorChecker(appContext).getFormFactor();
253
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700254 mPackageStatusNotifier = injector.getPackageStatusNotifier(appContext);
255
Jon Miranda16ea1b12017-12-12 14:52:48 -0800256 mWallpapers = new ArrayList<>();
257 mRandom = new Random();
258 mHandler = new Handler();
259
260 String collectionId = getArguments().getString(ARG_CATEGORY_COLLECTION_ID);
261 mCategory = (WallpaperCategory) injector.getCategoryProvider(appContext).getCategory(
262 collectionId);
263 if (mCategory == null) {
264 DiskBasedLogger.e(TAG, "Failed to find the category.", appContext);
265
266 // The absence of this category in the CategoryProvider indicates a broken state, probably due
267 // to a relaunch into this activity/fragment following a crash immediately prior; see
268 // b//38030129. Hence, finish the activity and return.
269 getActivity().finish();
270 return;
271 }
272
273 mWallpaperRotationInitializer = mCategory.getWallpaperRotationInitializer();
274
Santiago Etchebehereb1854472019-06-06 17:44:54 -0700275 // Clear Glide's cache if night-mode changed to ensure thumbnails are reloaded
276 if (savedInstanceState != null && (savedInstanceState.getInt(KEY_NIGHT_MODE)
277 != (getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK))) {
278 Glide.get(getContext()).clearMemory();
279 }
280
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700281 fetchWallpapers(false);
282
283 if (mCategory.supportsThirdParty()) {
284 mAppStatusListener = (packageName, status) -> {
285 if (status != PackageStatusNotifier.PackageStatus.REMOVED ||
286 mCategory.containsThirdParty(packageName)) {
287 fetchWallpapers(true);
288 }
289 };
290 mPackageStatusNotifier.addListener(mAppStatusListener,
291 WallpaperService.SERVICE_INTERFACE);
292 }
293 }
294
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800295 void fetchWallpapers(boolean forceReload) {
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700296 mWallpapers.clear();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800297 mCategory.fetchWallpapers(getActivity().getApplicationContext(), new WallpaperReceiver() {
298 @Override
299 public void onWallpapersReceived(List<WallpaperInfo> wallpapers) {
300 for (WallpaperInfo wallpaper : wallpapers) {
301 mWallpapers.add(wallpaper);
302 }
303
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700304 // Wallpapers may load after the adapter is initialized, in which case we have
305 // to explicitly notify that the data set has changed.
Jon Miranda16ea1b12017-12-12 14:52:48 -0800306 if (mAdapter != null) {
307 mAdapter.notifyDataSetChanged();
308 }
309
310 if (mWallpapersUiContainer != null) {
311 mWallpapersUiContainer.onWallpapersReady();
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700312 } else {
313 if (wallpapers.isEmpty()) {
314 // If there are no more wallpapers and we're on phone, just finish the
315 // Activity.
316 Activity activity = getActivity();
317 if (activity != null
318 && mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE) {
319 activity.finish();
320 }
321 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800322 }
323 }
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700324 }, forceReload);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800325 }
326
327 @Override
Santiago Etchebehereb1854472019-06-06 17:44:54 -0700328 public void onSaveInstanceState(@NonNull Bundle outState) {
329 super.onSaveInstanceState(outState);
Santiago Etchebehere0ec065c2019-06-13 11:30:21 -0700330 outState.putInt(KEY_NIGHT_MODE,
Santiago Etchebehereb1854472019-06-06 17:44:54 -0700331 getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK);
332 }
333
334 @Override
Jon Miranda16ea1b12017-12-12 14:52:48 -0800335 public View onCreateView(LayoutInflater inflater, ViewGroup container,
336 Bundle savedInstanceState) {
337 View view = inflater.inflate(R.layout.fragment_individual_picker, container, false);
338
339 mTileSizePx = TileSizeCalculator.getIndividualTileSize(getActivity());
340
341 mImageGrid = (RecyclerView) view.findViewById(R.id.wallpaper_grid);
342 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
343 int gridPaddingPx = getResources().getDimensionPixelSize(R.dimen.grid_padding_desktop);
344 updateImageGridPadding(false /* addExtraBottomSpace */);
345 mImageGrid.setScrollBarSize(gridPaddingPx);
346 }
347 GridMarginDecoration.applyTo(mImageGrid);
348
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800349 setUpImageGrid();
Jon Miranda16ea1b12017-12-12 14:52:48 -0800350 setUpBottomSheet();
351
352 return view;
353 }
354
355 @Override
356 public void onClickTryAgain(@Destination int unused) {
357 if (mPendingSetIndividualHolder != null) {
358 mPendingSetIndividualHolder.setWallpaper();
359 }
360 }
361
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800362 void updateImageGridPadding(boolean addExtraBottomSpace) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800363 int gridPaddingPx = getResources().getDimensionPixelSize(R.dimen.grid_padding_desktop);
364 int bottomSheetHeightPx = getResources().getDimensionPixelSize(
365 R.dimen.current_wallpaper_bottom_sheet_layout_height);
366 int paddingBottomPx = addExtraBottomSpace ? bottomSheetHeightPx : 0;
367 // Only left and top may be set in order for the GridMarginDecoration to work properly.
368 mImageGrid.setPadding(
369 gridPaddingPx, gridPaddingPx, 0, paddingBottomPx);
370 }
371
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800372 void setUpImageGrid() {
373 mAdapter = new IndividualAdapter(mWallpapers);
374 mImageGrid.setAdapter(mAdapter);
375 mImageGrid.setLayoutManager(new GridLayoutManager(getActivity(), getNumColumns()));
376 }
377
Jon Miranda16ea1b12017-12-12 14:52:48 -0800378 /**
379 * Enables and populates the "Currently set" wallpaper BottomSheet.
380 */
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800381 void setUpBottomSheet() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800382 mImageGrid.addOnScrollListener(new OnScrollListener() {
383 @Override
384 public void onScrolled(RecyclerView recyclerView, int dx, final int dy) {
385 if (mCurrentWallpaperBottomSheetPresenter == null) {
386 return;
387 }
388
389 if (mCurrentWallpaperBottomSheetExpandedRunnable != null) {
390 mHandler.removeCallbacks(mCurrentWallpaperBottomSheetExpandedRunnable);
391 }
392 mCurrentWallpaperBottomSheetExpandedRunnable = new Runnable() {
393 @Override
394 public void run() {
395 if (dy > 0) {
396 mCurrentWallpaperBottomSheetPresenter.setCurrentWallpapersExpanded(false);
397 } else {
398 mCurrentWallpaperBottomSheetPresenter.setCurrentWallpapersExpanded(true);
399 }
400 }
401 };
402 mHandler.postDelayed(mCurrentWallpaperBottomSheetExpandedRunnable, 100);
403 }
404 });
405 }
406
407 @Override
408 public void onResume() {
409 super.onResume();
410
411 WallpaperPreferences preferences = InjectorProvider.getInjector().getPreferences(getActivity());
412 preferences.setLastAppActiveTimestamp(new Date().getTime());
413
414 // Reset Glide memory settings to a "normal" level of usage since it may have been lowered in
415 // PreviewFragment.
416 Glide.get(getActivity()).setMemoryCategory(MemoryCategory.NORMAL);
417
418 // Show the staged 'start rotation' error dialog fragment if there is one that was unable to be
419 // shown earlier when this fragment's hosting activity didn't allow committing fragment
420 // transactions.
421 if (mStagedStartRotationErrorDialogFragment != null) {
422 mStagedStartRotationErrorDialogFragment.show(
423 getFragmentManager(), TAG_START_ROTATION_ERROR_DIALOG);
424 mStagedStartRotationErrorDialogFragment = null;
425 }
426
427 // Show the staged 'load wallpaper' or 'set wallpaper' error dialog fragments if there is one
428 // that was unable to be shown earlier when this fragment's hosting activity didn't allow
429 // committing fragment transactions.
430 if (mStagedSetWallpaperErrorDialogFragment != null) {
431 mStagedSetWallpaperErrorDialogFragment.show(
432 getFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
433 mStagedSetWallpaperErrorDialogFragment = null;
434 }
435
436 if (isRotationEnabled()) {
437 if (mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE) {
438 // Refresh the state of the "start rotation" in case something changed the current daily
439 // rotation while this fragment was paused.
440 RotationHolder rotationHolder = (RotationHolder) mImageGrid
441 .findViewHolderForAdapterPosition(
442 SPECIAL_FIXED_TILE_ADAPTER_POSITION);
443 // The RotationHolder may be null if the RecyclerView has not created the view
444 // holder yet.
445 if (rotationHolder != null && Flags.dynamicStartRotationTileEnabled) {
446 refreshRotationHolder(rotationHolder);
447 }
448 } else if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
449 if (mWasUpdateRunnableRun && !mWallpapers.isEmpty()) {
450 // Must be resuming from a previously stopped state, so re-schedule the update of the
451 // daily wallpapers tile thumbnail.
452 mUpdateDailyWallpaperThumbRunnable.run();
453 }
454 }
455 }
456
457 }
458
459 @Override
460 public void onStop() {
461 super.onStop();
462 mHandler.removeCallbacks(mUpdateDailyWallpaperThumbRunnable);
463 }
464
465 @Override
466 public void onDestroy() {
467 super.onDestroy();
468 if (mProgressDialog != null) {
469 mProgressDialog.dismiss();
470 }
471 mWallpaperChangedNotifier.unregisterListener(mWallpaperChangedListener);
Santiago Etchebehere1ee76a22018-05-15 15:02:24 -0700472 if (mAppStatusListener != null) {
473 mPackageStatusNotifier.removeListener(mAppStatusListener);
474 }
Jon Miranda16ea1b12017-12-12 14:52:48 -0800475 }
476
477 @Override
478 public void retryStartRotation(@NetworkPreference int networkPreference) {
479 startRotation(networkPreference);
480 }
481
482 public void setCurrentWallpaperBottomSheetPresenter(
483 CurrentWallpaperBottomSheetPresenter presenter) {
484 mCurrentWallpaperBottomSheetPresenter = presenter;
485 }
486
487 public void setWallpapersUiContainer(WallpapersUiContainer uiContainer) {
488 mWallpapersUiContainer = uiContainer;
489 }
490
491 /**
492 * Enable a test mode of operation -- in which certain UI features are disabled to allow for
493 * UI tests to run correctly. Works around issue in ProgressDialog currently where the dialog
494 * constantly keeps the UI thread alive and blocks a test forever.
495 *
496 * @param testingMode
497 */
498 void setTestingMode(boolean testingMode) {
499 mTestingMode = testingMode;
500 }
501
502 /**
503 * Asynchronously fetches the refreshed rotation initialization state that is up to date with the
504 * state of the user's device and binds the state of the current category's rotation to the "start
505 * rotation" tile.
506 */
507 private void refreshRotationHolder(final RotationHolder rotationHolder) {
508 mWallpaperRotationInitializer.fetchRotationInitializationState(getContext(),
509 new RotationStateListener() {
510 @Override
511 public void onRotationStateReceived(
512 @RotationInitializationState final int rotationInitializationState) {
513
514 // Update the UI state of the "start rotation" tile displayed on screen. Do this in a
515 // Handler so it is scheduled at the end of the message queue. This is necessary to
516 // ensure we do not remove or add data from the adapter while the layout is still being
517 // computed. RecyclerView documentation therefore recommends performing such changes in
518 // a Handler.
519 new android.os.Handler().post(new Runnable() {
520 @Override
521 public void run() {
522 // A config change may have destroyed the activity since the refresh started, so
523 // check for that to avoid an NPE.
524 if (getActivity() == null) {
525 return;
526 }
527
528 rotationHolder.bindRotationInitializationState(rotationInitializationState);
529 }
530 });
531 }
532 });
533 }
534
535 @Override
536 public void startRotation(@NetworkPreference final int networkPreference) {
537 if (!isRotationEnabled()) {
538 Log.e(TAG, "Rotation is not enabled for this category " + mCategory.getTitle());
539 return;
540 }
541
542 // ProgressDialog endlessly updates the UI thread, keeping it from going idle which therefore
543 // causes Espresso to hang once the dialog is shown.
544 if (mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE && !mTestingMode) {
545 int themeResId;
546 if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
547 themeResId = R.style.ProgressDialogThemePreL;
548 } else {
549 themeResId = R.style.LightDialogTheme;
550 }
551 mProgressDialog = new ProgressDialog(getActivity(), themeResId);
552
553 mProgressDialog.setTitle(PROGRESS_DIALOG_NO_TITLE);
554 mProgressDialog.setMessage(
555 getResources().getString(R.string.start_rotation_progress_message));
556 mProgressDialog.setIndeterminate(PROGRESS_DIALOG_INDETERMINATE);
557 mProgressDialog.show();
558 }
559
560 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
561 mAdapter.mPendingSelectedAdapterPosition = SPECIAL_FIXED_TILE_ADAPTER_POSITION;
562 }
563
564 final Context appContext = getActivity().getApplicationContext();
565
566 mWallpaperRotationInitializer.setFirstWallpaperInRotation(
567 appContext,
568 networkPreference,
569 new Listener() {
570 @Override
571 public void onFirstWallpaperInRotationSet() {
572 if (mProgressDialog != null) {
573 mProgressDialog.dismiss();
574 }
575
576 // The fragment may be detached from its containing activity if the user exits the
577 // app before the first wallpaper image in rotation finishes downloading.
578 Activity activity = getActivity();
579
580 if (activity != null
581 && mWallpaperRotationInitializer
582 .isNoBackupImageWallpaperPreviewNeeded(appContext)) {
583 ((IndividualPickerActivity) activity).showNoBackupImageWallpaperPreview();
584 } else {
585 if (mWallpaperRotationInitializer.startRotation(appContext)) {
586 if (activity != null && mFormFactor == FormFactorChecker.FORM_FACTOR_MOBILE) {
587 try {
588 Toast.makeText(getActivity(), R.string.wallpaper_set_successfully_message,
589 Toast.LENGTH_SHORT).show();
590 } catch (NotFoundException e) {
591 Log.e(TAG, "Could not show toast " + e);
592 }
593
594 activity.setResult(Activity.RESULT_OK);
595 activity.finish();
596 } else if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
597 mAdapter.updateSelectedTile(SPECIAL_FIXED_TILE_ADAPTER_POSITION);
598 }
599 } else { // Failed to start rotation.
600 showStartRotationErrorDialog(networkPreference);
601
602 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
603 DesktopRotationHolder rotationViewHolder =
604 (DesktopRotationHolder) mImageGrid.findViewHolderForAdapterPosition(
605 SPECIAL_FIXED_TILE_ADAPTER_POSITION);
606 rotationViewHolder.setSelectionState(SelectableHolder.SELECTION_STATE_DESELECTED);
607 }
608 }
609 }
610 }
611
612 @Override
613 public void onError() {
614 if (mProgressDialog != null) {
615 mProgressDialog.dismiss();
616 }
617
618 showStartRotationErrorDialog(networkPreference);
619
620 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
621 DesktopRotationHolder rotationViewHolder =
622 (DesktopRotationHolder) mImageGrid.findViewHolderForAdapterPosition(
623 SPECIAL_FIXED_TILE_ADAPTER_POSITION);
624 rotationViewHolder.setSelectionState(SelectableHolder.SELECTION_STATE_DESELECTED);
625 }
626 }
627 });
628 }
629
630 private void showStartRotationErrorDialog(@NetworkPreference int networkPreference) {
631 BaseActivity activity = (BaseActivity) getActivity();
632 if (activity != null) {
633 StartRotationErrorDialogFragment startRotationErrorDialogFragment =
634 StartRotationErrorDialogFragment.newInstance(networkPreference);
635 startRotationErrorDialogFragment.setTargetFragment(
636 IndividualPickerFragment.this, UNUSED_REQUEST_CODE);
637
638 if (activity.isSafeToCommitFragmentTransaction()) {
639 startRotationErrorDialogFragment.show(
640 getFragmentManager(), TAG_START_ROTATION_ERROR_DIALOG);
641 } else {
642 mStagedStartRotationErrorDialogFragment = startRotationErrorDialogFragment;
643 }
644 }
645 }
646
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800647 int getNumColumns() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800648 return TileSizeCalculator.getNumIndividualColumns(getActivity());
649 }
650
651 /**
652 * Returns whether rotation is enabled for this category.
653 */
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800654 boolean isRotationEnabled() {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800655 boolean isRotationSupported =
656 mRotatingWallpaperComponentChecker.getRotatingWallpaperSupport(getContext())
657 == RotatingWallpaperComponentChecker.ROTATING_WALLPAPER_SUPPORT_SUPPORTED;
658
659 return isRotationSupported && mWallpaperRotationInitializer != null;
660 }
661
662 @Override
663 public void onCurrentWallpaperRefreshed() {
664 mCurrentWallpaperBottomSheetPresenter.setCurrentWallpapersExpanded(true);
665 }
666
667 /**
668 * Shows a "set wallpaper" error dialog with a failure message and button to try again.
669 */
670 private void showSetWallpaperErrorDialog() {
671 SetWallpaperErrorDialogFragment dialogFragment = SetWallpaperErrorDialogFragment.newInstance(
672 R.string.set_wallpaper_error_message, WallpaperPersister.DEST_BOTH);
673 dialogFragment.setTargetFragment(this, UNUSED_REQUEST_CODE);
674
675 if (((BaseActivity) getActivity()).isSafeToCommitFragmentTransaction()) {
676 dialogFragment.show(getFragmentManager(), TAG_SET_WALLPAPER_ERROR_DIALOG_FRAGMENT);
677 } else {
678 mStagedSetWallpaperErrorDialogFragment = dialogFragment;
679 }
680 }
681
682 /**
683 * ViewHolder subclass for "daily refresh" tile in the RecyclerView, only shown if rotation is
684 * enabled for this category.
685 */
686 private class RotationHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
687
688 private FrameLayout mTileLayout;
689 private TextView mRotationMessage;
690 private TextView mRotationTitle;
691 private ImageView mRefreshIcon;
692
693 RotationHolder(View itemView) {
694 super(itemView);
695 itemView.setOnClickListener(this);
696
697 mTileLayout = (FrameLayout) itemView.findViewById(R.id.daily_refresh);
698 mRotationMessage = (TextView) itemView.findViewById(R.id.rotation_tile_message);
699 mRotationTitle = (TextView) itemView.findViewById(R.id.rotation_tile_title);
700 mRefreshIcon = (ImageView) itemView.findViewById(R.id.rotation_tile_refresh_icon);
701 mTileLayout.getLayoutParams().height = mTileSizePx.y;
702
703 // If the feature flag for "dynamic start rotation tile" is not enabled, fall back to the
704 // static UI with a blue accent color background and "Tap to turn on" text.
705 if (!Flags.dynamicStartRotationTileEnabled) {
706 mTileLayout.setBackgroundColor(
707 getResources().getColor(R.color.rotation_tile_enabled_background_color));
708 mRotationMessage.setText(R.string.daily_refresh_tile_subtitle);
709 mRotationTitle.setTextColor(
710 getResources().getColor(R.color.rotation_tile_enabled_title_text_color));
711 mRotationMessage.setTextColor(
712 getResources().getColor(R.color.rotation_tile_enabled_subtitle_text_color));
713 mRefreshIcon.setColorFilter(
714 getResources().getColor(R.color.rotation_tile_enabled_refresh_icon_color), Mode.SRC_IN);
715 return;
716 }
717
718 // Initialize the state of the "start rotation" tile (i.e., whether it is gray or blue to
719 // indicate if rotation is turned on for the current category) with last-known rotation state
720 // that could be stale. The last-known rotation state is correct in most cases and is a good
721 // starting point but may not be accurate if the user set a wallpaper through a 3rd party app
722 // while this app was paused.
723 int rotationState = mWallpaperRotationInitializer.getRotationInitializationStateDirty(
724 getContext());
725 bindRotationInitializationState(rotationState);
726 }
727
728 @Override
729 public void onClick(View v) {
730 boolean isLiveWallpaperNeeded = mWallpaperRotationInitializer
731 .isNoBackupImageWallpaperPreviewNeeded(getActivity().getApplicationContext());
732 DialogFragment startRotationDialogFragment = StartRotationDialogFragment
733 .newInstance(isLiveWallpaperNeeded);
734 startRotationDialogFragment.setTargetFragment(
735 IndividualPickerFragment.this, UNUSED_REQUEST_CODE);
736 startRotationDialogFragment.show(getFragmentManager(), TAG_START_ROTATION_DIALOG);
737 }
738
739 /**
740 * Binds the provided rotation initialization state to the RotationHolder and updates the tile's
741 * UI to be in sync with the state (i.e., message and color appropriately reflect the state to
742 * the user).
743 */
744 void bindRotationInitializationState(@RotationInitializationState int rotationState) {
745 int newBackgroundColor =
746 (rotationState == WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED)
747 ? getResources().getColor(R.color.rotation_tile_not_enabled_background_color)
748 : getResources().getColor(R.color.rotation_tile_enabled_background_color);
749 int newTitleTextColor =
750 (rotationState == WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED)
751 ? getResources().getColor(R.color.rotation_tile_not_enabled_title_text_color)
752 : getResources().getColor(R.color.rotation_tile_enabled_title_text_color);
753 int newSubtitleTextColor =
754 (rotationState == WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED)
755 ? getResources().getColor(R.color.rotation_tile_not_enabled_subtitle_text_color)
756 : getResources().getColor(R.color.rotation_tile_enabled_subtitle_text_color);
757 int newRefreshIconColor =
758 (rotationState == WallpaperRotationInitializer.ROTATION_NOT_INITIALIZED)
759 ? getResources().getColor(R.color.rotation_tile_not_enabled_refresh_icon_color)
760 : getResources().getColor(R.color.rotation_tile_enabled_refresh_icon_color);
761
762 mTileLayout.setBackgroundColor(newBackgroundColor);
763 mRotationTitle.setTextColor(newTitleTextColor);
764 mRotationMessage.setText(getResIdForRotationState(rotationState));
765 mRotationMessage.setTextColor(newSubtitleTextColor);
766 mRefreshIcon.setColorFilter(newRefreshIconColor, Mode.SRC_IN);
767 }
768 }
769
770 /**
771 * RecyclerView Adapter subclass for the wallpaper tiles in the RecyclerView.
772 */
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800773 class IndividualAdapter extends RecyclerView.Adapter<ViewHolder> {
774 static final int ITEM_VIEW_TYPE_ROTATION = 1;
775 static final int ITEM_VIEW_TYPE_INDIVIDUAL_WALLPAPER = 2;
776 static final int ITEM_VIEW_TYPE_MY_PHOTOS = 3;
Jon Miranda16ea1b12017-12-12 14:52:48 -0800777
778 private final List<WallpaperInfo> mWallpapers;
779
780 private int mPendingSelectedAdapterPosition;
781 private int mSelectedAdapterPosition;
782
783 IndividualAdapter(List<WallpaperInfo> wallpapers) {
784 mWallpapers = wallpapers;
785 mPendingSelectedAdapterPosition = -1;
786 mSelectedAdapterPosition = -1;
787 }
788
789 @Override
790 public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
791 switch (viewType) {
792 case ITEM_VIEW_TYPE_ROTATION:
793 return createRotationHolder(parent);
794 case ITEM_VIEW_TYPE_INDIVIDUAL_WALLPAPER:
795 return createIndividualHolder(parent);
796 case ITEM_VIEW_TYPE_MY_PHOTOS:
797 return createMyPhotosHolder(parent);
798 default:
799 Log.e(TAG, "Unsupported viewType " + viewType + " in IndividualAdapter");
800 return null;
801 }
802 }
803
804 @Override
805 public int getItemViewType(int position) {
806 if (isRotationEnabled() && position == SPECIAL_FIXED_TILE_ADAPTER_POSITION) {
807 return ITEM_VIEW_TYPE_ROTATION;
808 }
809
810 // A category cannot have both a "start rotation" tile and a "my photos" tile.
811 if (mCategory.supportsCustomPhotos()
812 && !isRotationEnabled()
813 && position == SPECIAL_FIXED_TILE_ADAPTER_POSITION) {
814 return ITEM_VIEW_TYPE_MY_PHOTOS;
815 }
816
817 return ITEM_VIEW_TYPE_INDIVIDUAL_WALLPAPER;
818 }
819
820 @Override
821 public void onBindViewHolder(ViewHolder holder, int position) {
822 int viewType = getItemViewType(position);
823
824 switch (viewType) {
825 case ITEM_VIEW_TYPE_ROTATION:
826 onBindRotationHolder(holder, position);
827 break;
828 case ITEM_VIEW_TYPE_INDIVIDUAL_WALLPAPER:
829 onBindIndividualHolder(holder, position);
830 break;
831 case ITEM_VIEW_TYPE_MY_PHOTOS:
832 ((MyPhotosViewHolder) holder).bind();
833 break;
834 default:
835 Log.e(TAG, "Unsupported viewType " + viewType + " in IndividualAdapter");
836 }
837 }
838
839 @Override
840 public int getItemCount() {
841 return (isRotationEnabled() || mCategory.supportsCustomPhotos())
842 ? mWallpapers.size() + 1
843 : mWallpapers.size();
844 }
845
846 private ViewHolder createRotationHolder(ViewGroup parent) {
847 LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
848 View view;
849
850 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
851 view = layoutInflater.inflate(R.layout.grid_item_rotation_desktop, parent, false);
852 SelectionAnimator selectionAnimator =
853 new CheckmarkSelectionAnimator(getActivity(), view);
854 return new DesktopRotationHolder(
855 getActivity(), mTileSizePx.y, view, selectionAnimator,
856 IndividualPickerFragment.this);
857 } else { // MOBILE
858 view = layoutInflater.inflate(R.layout.grid_item_rotation, parent, false);
859 return new RotationHolder(view);
860 }
861 }
862
863 private ViewHolder createIndividualHolder(ViewGroup parent) {
864 LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
865 View view = layoutInflater.inflate(R.layout.grid_item_image, parent, false);
866
867 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
868 SelectionAnimator selectionAnimator =
869 new CheckmarkSelectionAnimator(getActivity(), view);
870 return new SetIndividualHolder(
871 getActivity(), mTileSizePx.y, view,
872 selectionAnimator,
873 new OnSetListener() {
874 @Override
875 public void onPendingWallpaperSet(int adapterPosition) {
876 // Deselect and hide loading indicator for any previously pending tile.
877 if (mPendingSelectedAdapterPosition != -1) {
878 ViewHolder oldViewHolder = mImageGrid.findViewHolderForAdapterPosition(
879 mPendingSelectedAdapterPosition);
880 if (oldViewHolder instanceof SelectableHolder) {
881 ((SelectableHolder) oldViewHolder).setSelectionState(
882 SelectableHolder.SELECTION_STATE_DESELECTED);
883 }
884 }
885
886 if (mSelectedAdapterPosition != -1) {
887 ViewHolder oldViewHolder = mImageGrid.findViewHolderForAdapterPosition(
888 mSelectedAdapterPosition);
889 if (oldViewHolder instanceof SelectableHolder) {
890 ((SelectableHolder) oldViewHolder).setSelectionState(
891 SelectableHolder.SELECTION_STATE_DESELECTED);
892 }
893 }
894
895 mPendingSelectedAdapterPosition = adapterPosition;
896 }
897
898 @Override
899 public void onWallpaperSet(int adapterPosition) {
900 // No-op -- UI handles a new wallpaper being set by reacting to the
901 // WallpaperChangedNotifier.
902 }
903
904 @Override
905 public void onWallpaperSetFailed(SetIndividualHolder holder) {
906 showSetWallpaperErrorDialog();
907 mPendingSetIndividualHolder = holder;
908 }
909 });
910 } else { // MOBILE
911 return new PreviewIndividualHolder(
912 (IndividualPickerActivity) getActivity(), mTileSizePx.y, view);
913 }
914 }
915
916 private ViewHolder createMyPhotosHolder(ViewGroup parent) {
917 LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
918 View view = layoutInflater.inflate(R.layout.grid_item_my_photos, parent, false);
919
Santiago Etchebeherefab49612019-01-15 12:22:42 -0800920 return new MyPhotosViewHolder(getActivity(),
921 ((MyPhotosStarterProvider) getActivity()).getMyPhotosStarter(),
922 mTileSizePx.y, view);
Jon Miranda16ea1b12017-12-12 14:52:48 -0800923 }
924
925 /**
926 * Marks the tile at the given position as selected with a visual indication. Also updates the
927 * "currently selected" BottomSheet to reflect the newly selected tile.
928 */
929 private void updateSelectedTile(int newlySelectedPosition) {
930 // Prevent multiple spinners from appearing with a user tapping several tiles in rapid
931 // succession.
932 if (mPendingSelectedAdapterPosition == mSelectedAdapterPosition) {
933 return;
934 }
935
936 if (mCurrentWallpaperBottomSheetPresenter != null) {
937 mCurrentWallpaperBottomSheetPresenter.refreshCurrentWallpapers(
938 IndividualPickerFragment.this);
939
940 if (mCurrentWallpaperBottomSheetExpandedRunnable != null) {
941 mHandler.removeCallbacks(mCurrentWallpaperBottomSheetExpandedRunnable);
942 }
943 mCurrentWallpaperBottomSheetExpandedRunnable = new Runnable() {
944 @Override
945 public void run() {
946 mCurrentWallpaperBottomSheetPresenter.setCurrentWallpapersExpanded(true);
947 }
948 };
949 mHandler.postDelayed(mCurrentWallpaperBottomSheetExpandedRunnable, 100);
950 }
951
952 // User may have switched to another category, thus detaching this fragment, so check here.
953 // NOTE: We do this check after updating the current wallpaper BottomSheet so that the update
954 // still occurs in the UI after the user selects that other category.
955 if (getActivity() == null) {
956 return;
957 }
958
959 // Update the newly selected wallpaper ViewHolder and the old one so that if
960 // selection UI state applies (desktop UI), it is updated.
961 if (mSelectedAdapterPosition >= 0) {
962 ViewHolder oldViewHolder = mImageGrid.findViewHolderForAdapterPosition(
963 mSelectedAdapterPosition);
964 if (oldViewHolder instanceof SelectableHolder) {
965 ((SelectableHolder) oldViewHolder).setSelectionState(
966 SelectableHolder.SELECTION_STATE_DESELECTED);
967 }
968 }
969
970 // Animate selection of newly selected tile.
971 ViewHolder newViewHolder = mImageGrid
972 .findViewHolderForAdapterPosition(newlySelectedPosition);
973 if (newViewHolder instanceof SelectableHolder) {
974 ((SelectableHolder) newViewHolder).setSelectionState(
975 SelectableHolder.SELECTION_STATE_SELECTED);
976 }
977
978 mSelectedAdapterPosition = newlySelectedPosition;
979
980 // If the tile was in the last row of the grid, add space below it so the user can scroll down
981 // and up to see the BottomSheet without it fully overlapping the newly selected tile.
982 int spanCount = ((GridLayoutManager) mImageGrid.getLayoutManager()).getSpanCount();
983 int numRows = (int) Math.ceil((float) getItemCount() / spanCount);
984 int rowOfNewlySelectedTile = newlySelectedPosition / spanCount;
985 boolean isInLastRow = rowOfNewlySelectedTile == numRows - 1;
986
987 updateImageGridPadding(isInLastRow /* addExtraBottomSpace */);
988 }
989
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +0800990 void onBindRotationHolder(ViewHolder holder, int position) {
Jon Miranda16ea1b12017-12-12 14:52:48 -0800991 if (mFormFactor == FormFactorChecker.FORM_FACTOR_DESKTOP) {
992 String collectionId = mCategory.getCollectionId();
993 ((DesktopRotationHolder) holder).bind(collectionId);
994
995 if (mWallpaperPreferences.getWallpaperPresentationMode()
996 == WallpaperPreferences.PRESENTATION_MODE_ROTATING
997 && collectionId.equals(mWallpaperPreferences.getHomeWallpaperCollectionId())) {
998 mSelectedAdapterPosition = position;
999 }
1000
1001 if (!mWasUpdateRunnableRun && !mWallpapers.isEmpty()) {
1002 updateDesktopDailyRotationThumbnail((DesktopRotationHolder) holder);
1003 mWasUpdateRunnableRun = true;
1004 }
1005 }
1006 }
1007
Ching-Sung Li31fbe5e2019-01-23 19:36:24 +08001008 void onBindIndividualHolder(ViewHolder holder, int position) {
Jon Miranda16ea1b12017-12-12 14:52:48 -08001009 int wallpaperIndex = (isRotationEnabled() || mCategory.supportsCustomPhotos())
1010 ? position - 1 : position;
1011 WallpaperInfo wallpaper = mWallpapers.get(wallpaperIndex);
1012 ((IndividualHolder) holder).bindWallpaper(wallpaper);
1013 WallpaperPreferences prefs = InjectorProvider.getInjector().getPreferences(getContext());
1014
1015 String wallpaperId = wallpaper.getWallpaperId();
1016 if (wallpaperId != null && wallpaperId.equals(prefs.getHomeWallpaperRemoteId())) {
1017 mSelectedAdapterPosition = position;
1018 }
1019 }
1020 }
1021}